OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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/dart_entry.h" |
11 #include "vm/flow_graph_compiler.h" | 12 #include "vm/flow_graph_compiler.h" |
12 #include "vm/locations.h" | 13 #include "vm/locations.h" |
13 #include "vm/object_store.h" | 14 #include "vm/object_store.h" |
14 #include "vm/parser.h" | 15 #include "vm/parser.h" |
15 #include "vm/stub_code.h" | 16 #include "vm/stub_code.h" |
16 #include "vm/symbols.h" | 17 #include "vm/symbols.h" |
17 | 18 |
18 #define __ compiler->assembler()-> | 19 #define __ compiler->assembler()-> |
19 | 20 |
20 namespace dart { | 21 namespace dart { |
(...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
260 | 261 |
261 | 262 |
262 LocationSummary* EqualityCompareInstr::MakeLocationSummary() const { | 263 LocationSummary* EqualityCompareInstr::MakeLocationSummary() const { |
263 const intptr_t kNumInputs = 2; | 264 const intptr_t kNumInputs = 2; |
264 const bool is_checked_strict_equal = | 265 const bool is_checked_strict_equal = |
265 HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid); | 266 HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid); |
266 if (receiver_class_id() == kMintCid) { | 267 if (receiver_class_id() == kMintCid) { |
267 const intptr_t kNumTemps = 1; | 268 const intptr_t kNumTemps = 1; |
268 LocationSummary* locs = | 269 LocationSummary* locs = |
269 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 270 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
270 locs->set_in(0, Location::RequiresXmmRegister()); | 271 locs->set_in(0, Location::RequiresFpuRegister()); |
271 locs->set_in(1, Location::RequiresXmmRegister()); | 272 locs->set_in(1, Location::RequiresFpuRegister()); |
272 locs->set_temp(0, Location::RequiresRegister()); | 273 locs->set_temp(0, Location::RequiresRegister()); |
273 locs->set_out(Location::RequiresRegister()); | 274 locs->set_out(Location::RequiresRegister()); |
274 return locs; | 275 return locs; |
275 } | 276 } |
276 if (receiver_class_id() == kDoubleCid) { | 277 if (receiver_class_id() == kDoubleCid) { |
277 const intptr_t kNumTemps = 0; | 278 const intptr_t kNumTemps = 0; |
278 LocationSummary* locs = | 279 LocationSummary* locs = |
279 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 280 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
280 locs->set_in(0, Location::RequiresXmmRegister()); | 281 locs->set_in(0, Location::RequiresFpuRegister()); |
281 locs->set_in(1, Location::RequiresXmmRegister()); | 282 locs->set_in(1, Location::RequiresFpuRegister()); |
282 locs->set_out(Location::RequiresRegister()); | 283 locs->set_out(Location::RequiresRegister()); |
283 return locs; | 284 return locs; |
284 } | 285 } |
285 if (receiver_class_id() == kSmiCid) { | 286 if (receiver_class_id() == kSmiCid) { |
286 const intptr_t kNumTemps = 0; | 287 const intptr_t kNumTemps = 0; |
287 LocationSummary* locs = | 288 LocationSummary* locs = |
288 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 289 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
289 locs->set_in(0, Location::RegisterOrConstant(left())); | 290 locs->set_in(0, Location::RegisterOrConstant(left())); |
290 // Only one input can be a constant operand. The case of two constant | 291 // Only one input can be a constant operand. The case of two constant |
291 // operands should be handled by constant propagation. | 292 // operands should be handled by constant propagation. |
(...skipping 365 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
657 return OVERFLOW; | 658 return OVERFLOW; |
658 } | 659 } |
659 } | 660 } |
660 | 661 |
661 | 662 |
662 static void EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler, | 663 static void EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler, |
663 const LocationSummary& locs, | 664 const LocationSummary& locs, |
664 Token::Kind kind, | 665 Token::Kind kind, |
665 BranchInstr* branch) { | 666 BranchInstr* branch) { |
666 ASSERT(Token::IsEqualityOperator(kind)); | 667 ASSERT(Token::IsEqualityOperator(kind)); |
667 XmmRegister left = locs.in(0).xmm_reg(); | 668 XmmRegister left = locs.in(0).fpu_reg(); |
668 XmmRegister right = locs.in(1).xmm_reg(); | 669 XmmRegister right = locs.in(1).fpu_reg(); |
669 Register temp = locs.temp(0).reg(); | 670 Register temp = locs.temp(0).reg(); |
670 __ movaps(XMM0, left); | 671 __ movaps(XMM0, left); |
671 __ pcmpeqq(XMM0, right); | 672 __ pcmpeqq(XMM0, right); |
672 __ movd(temp, XMM0); | 673 __ movd(temp, XMM0); |
673 | 674 |
674 Condition true_condition = TokenKindToMintCondition(kind); | 675 Condition true_condition = TokenKindToMintCondition(kind); |
675 __ cmpl(temp, Immediate(-1)); | 676 __ cmpl(temp, Immediate(-1)); |
676 | 677 |
677 if (branch != NULL) { | 678 if (branch != NULL) { |
678 branch->EmitBranchOnCondition(compiler, true_condition); | 679 branch->EmitBranchOnCondition(compiler, true_condition); |
679 } else { | 680 } else { |
680 Register result = locs.out().reg(); | 681 Register result = locs.out().reg(); |
681 Label done, is_true; | 682 Label done, is_true; |
682 __ j(true_condition, &is_true); | 683 __ j(true_condition, &is_true); |
683 __ LoadObject(result, Bool::False()); | 684 __ LoadObject(result, Bool::False()); |
684 __ jmp(&done); | 685 __ jmp(&done); |
685 __ Bind(&is_true); | 686 __ Bind(&is_true); |
686 __ LoadObject(result, Bool::True()); | 687 __ LoadObject(result, Bool::True()); |
687 __ Bind(&done); | 688 __ Bind(&done); |
688 } | 689 } |
689 } | 690 } |
690 | 691 |
691 | 692 |
692 static void EmitUnboxedMintComparisonOp(FlowGraphCompiler* compiler, | 693 static void EmitUnboxedMintComparisonOp(FlowGraphCompiler* compiler, |
693 const LocationSummary& locs, | 694 const LocationSummary& locs, |
694 Token::Kind kind, | 695 Token::Kind kind, |
695 BranchInstr* branch) { | 696 BranchInstr* branch) { |
696 XmmRegister left = locs.in(0).xmm_reg(); | 697 XmmRegister left = locs.in(0).fpu_reg(); |
697 XmmRegister right = locs.in(1).xmm_reg(); | 698 XmmRegister right = locs.in(1).fpu_reg(); |
698 Register left_tmp = locs.temp(0).reg(); | 699 Register left_tmp = locs.temp(0).reg(); |
699 Register right_tmp = locs.temp(1).reg(); | 700 Register right_tmp = locs.temp(1).reg(); |
700 Register result = branch == NULL ? locs.out().reg() : kNoRegister; | 701 Register result = branch == NULL ? locs.out().reg() : kNoRegister; |
701 | 702 |
702 Condition hi_cond = OVERFLOW, lo_cond = OVERFLOW; | 703 Condition hi_cond = OVERFLOW, lo_cond = OVERFLOW; |
703 switch (kind) { | 704 switch (kind) { |
704 case Token::kLT: | 705 case Token::kLT: |
705 hi_cond = LESS; | 706 hi_cond = LESS; |
706 lo_cond = BELOW; | 707 lo_cond = BELOW; |
707 break; | 708 break; |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
766 UNREACHABLE(); | 767 UNREACHABLE(); |
767 return OVERFLOW; | 768 return OVERFLOW; |
768 } | 769 } |
769 } | 770 } |
770 | 771 |
771 | 772 |
772 static void EmitDoubleComparisonOp(FlowGraphCompiler* compiler, | 773 static void EmitDoubleComparisonOp(FlowGraphCompiler* compiler, |
773 const LocationSummary& locs, | 774 const LocationSummary& locs, |
774 Token::Kind kind, | 775 Token::Kind kind, |
775 BranchInstr* branch) { | 776 BranchInstr* branch) { |
776 XmmRegister left = locs.in(0).xmm_reg(); | 777 XmmRegister left = locs.in(0).fpu_reg(); |
777 XmmRegister right = locs.in(1).xmm_reg(); | 778 XmmRegister right = locs.in(1).fpu_reg(); |
778 | 779 |
779 Condition true_condition = TokenKindToDoubleCondition(kind); | 780 Condition true_condition = TokenKindToDoubleCondition(kind); |
780 if (branch != NULL) { | 781 if (branch != NULL) { |
781 compiler->EmitDoubleCompareBranch( | 782 compiler->EmitDoubleCompareBranch( |
782 true_condition, left, right, branch); | 783 true_condition, left, right, branch); |
783 } else { | 784 } else { |
784 compiler->EmitDoubleCompareBool( | 785 compiler->EmitDoubleCompareBool( |
785 true_condition, left, right, locs.out().reg()); | 786 true_condition, left, right, locs.out().reg()); |
786 } | 787 } |
787 } | 788 } |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
876 } | 877 } |
877 | 878 |
878 | 879 |
879 LocationSummary* RelationalOpInstr::MakeLocationSummary() const { | 880 LocationSummary* RelationalOpInstr::MakeLocationSummary() const { |
880 const intptr_t kNumInputs = 2; | 881 const intptr_t kNumInputs = 2; |
881 const intptr_t kNumTemps = 0; | 882 const intptr_t kNumTemps = 0; |
882 if (operands_class_id() == kMintCid) { | 883 if (operands_class_id() == kMintCid) { |
883 const intptr_t kNumTemps = 2; | 884 const intptr_t kNumTemps = 2; |
884 LocationSummary* locs = | 885 LocationSummary* locs = |
885 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 886 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
886 locs->set_in(0, Location::RequiresXmmRegister()); | 887 locs->set_in(0, Location::RequiresFpuRegister()); |
887 locs->set_in(1, Location::RequiresXmmRegister()); | 888 locs->set_in(1, Location::RequiresFpuRegister()); |
888 locs->set_temp(0, Location::RequiresRegister()); | 889 locs->set_temp(0, Location::RequiresRegister()); |
889 locs->set_temp(1, Location::RequiresRegister()); | 890 locs->set_temp(1, Location::RequiresRegister()); |
890 locs->set_out(Location::RequiresRegister()); | 891 locs->set_out(Location::RequiresRegister()); |
891 return locs; | 892 return locs; |
892 } | 893 } |
893 if (operands_class_id() == kDoubleCid) { | 894 if (operands_class_id() == kDoubleCid) { |
894 LocationSummary* summary = | 895 LocationSummary* summary = |
895 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 896 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
896 summary->set_in(0, Location::RequiresXmmRegister()); | 897 summary->set_in(0, Location::RequiresFpuRegister()); |
897 summary->set_in(1, Location::RequiresXmmRegister()); | 898 summary->set_in(1, Location::RequiresFpuRegister()); |
898 summary->set_out(Location::RequiresRegister()); | 899 summary->set_out(Location::RequiresRegister()); |
899 return summary; | 900 return summary; |
900 } else if (operands_class_id() == kSmiCid) { | 901 } else if (operands_class_id() == kSmiCid) { |
901 LocationSummary* summary = | 902 LocationSummary* summary = |
902 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 903 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
903 summary->set_in(0, Location::RegisterOrConstant(left())); | 904 summary->set_in(0, Location::RegisterOrConstant(left())); |
904 // Only one input can be a constant operand. The case of two constant | 905 // Only one input can be a constant operand. The case of two constant |
905 // operands should be handled by constant propagation. | 906 // operands should be handled by constant propagation. |
906 summary->set_in(1, summary->in(0).IsConstant() | 907 summary->set_in(1, summary->in(0).IsConstant() |
907 ? Location::RequiresRegister() | 908 ? Location::RequiresRegister() |
(...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1138 LocationSummary* LoadIndexedInstr::MakeLocationSummary() const { | 1139 LocationSummary* LoadIndexedInstr::MakeLocationSummary() const { |
1139 const intptr_t kNumInputs = 2; | 1140 const intptr_t kNumInputs = 2; |
1140 const intptr_t kNumTemps = 0; | 1141 const intptr_t kNumTemps = 0; |
1141 LocationSummary* locs = | 1142 LocationSummary* locs = |
1142 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1143 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
1143 locs->set_in(0, Location::RequiresRegister()); | 1144 locs->set_in(0, Location::RequiresRegister()); |
1144 locs->set_in(1, CanBeImmediateIndex(index(), class_id()) | 1145 locs->set_in(1, CanBeImmediateIndex(index(), class_id()) |
1145 ? Location::RegisterOrSmiConstant(index()) | 1146 ? Location::RegisterOrSmiConstant(index()) |
1146 : Location::RequiresRegister()); | 1147 : Location::RequiresRegister()); |
1147 if (representation() == kUnboxedDouble) { | 1148 if (representation() == kUnboxedDouble) { |
1148 locs->set_out(Location::RequiresXmmRegister()); | 1149 locs->set_out(Location::RequiresFpuRegister()); |
1149 } else { | 1150 } else { |
1150 locs->set_out(Location::RequiresRegister()); | 1151 locs->set_out(Location::RequiresRegister()); |
1151 } | 1152 } |
1152 return locs; | 1153 return locs; |
1153 } | 1154 } |
1154 | 1155 |
1155 | 1156 |
1156 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1157 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
1157 Register array = locs()->in(0).reg(); | 1158 Register array = locs()->in(0).reg(); |
1158 Location index = locs()->in(1); | 1159 Location index = locs()->in(1); |
(...skipping 18 matching lines...) Expand all Loading... |
1177 return; | 1178 return; |
1178 } | 1179 } |
1179 | 1180 |
1180 FieldAddress element_address = index.IsRegister() ? | 1181 FieldAddress element_address = index.IsRegister() ? |
1181 FlowGraphCompiler::ElementAddressForRegIndex( | 1182 FlowGraphCompiler::ElementAddressForRegIndex( |
1182 class_id(), array, index.reg()) : | 1183 class_id(), array, index.reg()) : |
1183 FlowGraphCompiler::ElementAddressForIntIndex( | 1184 FlowGraphCompiler::ElementAddressForIntIndex( |
1184 class_id(), array, Smi::Cast(index.constant()).Value()); | 1185 class_id(), array, Smi::Cast(index.constant()).Value()); |
1185 | 1186 |
1186 if (representation() == kUnboxedDouble) { | 1187 if (representation() == kUnboxedDouble) { |
1187 XmmRegister result = locs()->out().xmm_reg(); | 1188 XmmRegister result = locs()->out().fpu_reg(); |
1188 if (class_id() == kFloat32ArrayCid) { | 1189 if (class_id() == kFloat32ArrayCid) { |
1189 // Load single precision float. | 1190 // Load single precision float. |
1190 __ movss(result, element_address); | 1191 __ movss(result, element_address); |
1191 // Promote to double. | 1192 // Promote to double. |
1192 __ cvtss2sd(result, locs()->out().xmm_reg()); | 1193 __ cvtss2sd(result, locs()->out().fpu_reg()); |
1193 } else { | 1194 } else { |
1194 ASSERT(class_id() == kFloat64ArrayCid); | 1195 ASSERT(class_id() == kFloat64ArrayCid); |
1195 __ movsd(result, element_address); | 1196 __ movsd(result, element_address); |
1196 } | 1197 } |
1197 return; | 1198 return; |
1198 } | 1199 } |
1199 | 1200 |
1200 Register result = locs()->out().reg(); | 1201 Register result = locs()->out().reg(); |
1201 if ((class_id() == kUint8ArrayCid) || | 1202 if ((class_id() == kUint8ArrayCid) || |
1202 (class_id() == kUint8ClampedArrayCid)) { | 1203 (class_id() == kUint8ClampedArrayCid)) { |
(...skipping 28 matching lines...) Expand all Loading... |
1231 ? Location::WritableRegister() | 1232 ? Location::WritableRegister() |
1232 : Location::RegisterOrConstant(value())); | 1233 : Location::RegisterOrConstant(value())); |
1233 break; | 1234 break; |
1234 case kUint8ArrayCid: | 1235 case kUint8ArrayCid: |
1235 // TODO(fschneider): Add location constraint for byte registers (EAX, | 1236 // TODO(fschneider): Add location constraint for byte registers (EAX, |
1236 // EBX, ECX, EDX) instead of using a fixed register. | 1237 // EBX, ECX, EDX) instead of using a fixed register. |
1237 locs->set_in(2, Location::FixedRegisterOrSmiConstant(value(), EAX)); | 1238 locs->set_in(2, Location::FixedRegisterOrSmiConstant(value(), EAX)); |
1238 break; | 1239 break; |
1239 case kFloat32ArrayCid: | 1240 case kFloat32ArrayCid: |
1240 // Need temp register for float-to-double conversion. | 1241 // Need temp register for float-to-double conversion. |
1241 locs->AddTemp(Location::RequiresXmmRegister()); | 1242 locs->AddTemp(Location::RequiresFpuRegister()); |
1242 // Fall through. | 1243 // Fall through. |
1243 case kFloat64ArrayCid: | 1244 case kFloat64ArrayCid: |
1244 // TODO(srdjan): Support Float64 constants. | 1245 // TODO(srdjan): Support Float64 constants. |
1245 locs->set_in(2, Location::RequiresXmmRegister()); | 1246 locs->set_in(2, Location::RequiresFpuRegister()); |
1246 break; | 1247 break; |
1247 default: | 1248 default: |
1248 UNREACHABLE(); | 1249 UNREACHABLE(); |
1249 return NULL; | 1250 return NULL; |
1250 } | 1251 } |
1251 return locs; | 1252 return locs; |
1252 } | 1253 } |
1253 | 1254 |
1254 | 1255 |
1255 void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1256 void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1287 ASSERT(locs()->in(2).reg() == EAX); | 1288 ASSERT(locs()->in(2).reg() == EAX); |
1288 __ SmiUntag(EAX); | 1289 __ SmiUntag(EAX); |
1289 __ movb(element_address, AL); | 1290 __ movb(element_address, AL); |
1290 } | 1291 } |
1291 if (index.IsRegister()) { | 1292 if (index.IsRegister()) { |
1292 __ SmiTag(index.reg()); // Re-tag. | 1293 __ SmiTag(index.reg()); // Re-tag. |
1293 } | 1294 } |
1294 break; | 1295 break; |
1295 case kFloat32ArrayCid: | 1296 case kFloat32ArrayCid: |
1296 // Convert to single precision. | 1297 // Convert to single precision. |
1297 __ cvtsd2ss(locs()->temp(0).xmm_reg(), locs()->in(2).xmm_reg()); | 1298 __ cvtsd2ss(locs()->temp(0).fpu_reg(), locs()->in(2).fpu_reg()); |
1298 // Store. | 1299 // Store. |
1299 __ movss(element_address, locs()->temp(0).xmm_reg()); | 1300 __ movss(element_address, locs()->temp(0).fpu_reg()); |
1300 break; | 1301 break; |
1301 case kFloat64ArrayCid: | 1302 case kFloat64ArrayCid: |
1302 __ movsd(element_address, locs()->in(2).xmm_reg()); | 1303 __ movsd(element_address, locs()->in(2).fpu_reg()); |
1303 break; | 1304 break; |
1304 default: | 1305 default: |
1305 UNREACHABLE(); | 1306 UNREACHABLE(); |
1306 } | 1307 } |
1307 } | 1308 } |
1308 | 1309 |
1309 | 1310 |
1310 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary() const { | 1311 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary() const { |
1311 const intptr_t kNumInputs = 2; | 1312 const intptr_t kNumInputs = 2; |
1312 const intptr_t num_temps = 0; | 1313 const intptr_t num_temps = 0; |
(...skipping 768 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2081 } | 2082 } |
2082 | 2083 |
2083 | 2084 |
2084 LocationSummary* BoxDoubleInstr::MakeLocationSummary() const { | 2085 LocationSummary* BoxDoubleInstr::MakeLocationSummary() const { |
2085 const intptr_t kNumInputs = 1; | 2086 const intptr_t kNumInputs = 1; |
2086 const intptr_t kNumTemps = 0; | 2087 const intptr_t kNumTemps = 0; |
2087 LocationSummary* summary = | 2088 LocationSummary* summary = |
2088 new LocationSummary(kNumInputs, | 2089 new LocationSummary(kNumInputs, |
2089 kNumTemps, | 2090 kNumTemps, |
2090 LocationSummary::kCallOnSlowPath); | 2091 LocationSummary::kCallOnSlowPath); |
2091 summary->set_in(0, Location::RequiresXmmRegister()); | 2092 summary->set_in(0, Location::RequiresFpuRegister()); |
2092 summary->set_out(Location::RequiresRegister()); | 2093 summary->set_out(Location::RequiresRegister()); |
2093 return summary; | 2094 return summary; |
2094 } | 2095 } |
2095 | 2096 |
2096 | 2097 |
2097 class BoxDoubleSlowPath : public SlowPathCode { | 2098 class BoxDoubleSlowPath : public SlowPathCode { |
2098 public: | 2099 public: |
2099 explicit BoxDoubleSlowPath(BoxDoubleInstr* instruction) | 2100 explicit BoxDoubleSlowPath(BoxDoubleInstr* instruction) |
2100 : instruction_(instruction) { } | 2101 : instruction_(instruction) { } |
2101 | 2102 |
(...skipping 22 matching lines...) Expand all Loading... |
2124 private: | 2125 private: |
2125 BoxDoubleInstr* instruction_; | 2126 BoxDoubleInstr* instruction_; |
2126 }; | 2127 }; |
2127 | 2128 |
2128 | 2129 |
2129 void BoxDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2130 void BoxDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2130 BoxDoubleSlowPath* slow_path = new BoxDoubleSlowPath(this); | 2131 BoxDoubleSlowPath* slow_path = new BoxDoubleSlowPath(this); |
2131 compiler->AddSlowPathCode(slow_path); | 2132 compiler->AddSlowPathCode(slow_path); |
2132 | 2133 |
2133 Register out_reg = locs()->out().reg(); | 2134 Register out_reg = locs()->out().reg(); |
2134 XmmRegister value = locs()->in(0).xmm_reg(); | 2135 XmmRegister value = locs()->in(0).fpu_reg(); |
2135 | 2136 |
2136 AssemblerMacros::TryAllocate(compiler->assembler(), | 2137 AssemblerMacros::TryAllocate(compiler->assembler(), |
2137 compiler->double_class(), | 2138 compiler->double_class(), |
2138 slow_path->entry_label(), | 2139 slow_path->entry_label(), |
2139 Assembler::kFarJump, | 2140 Assembler::kFarJump, |
2140 out_reg); | 2141 out_reg); |
2141 __ Bind(slow_path->exit_label()); | 2142 __ Bind(slow_path->exit_label()); |
2142 __ movsd(FieldAddress(out_reg, Double::value_offset()), value); | 2143 __ movsd(FieldAddress(out_reg, Double::value_offset()), value); |
2143 } | 2144 } |
2144 | 2145 |
2145 | 2146 |
2146 LocationSummary* UnboxDoubleInstr::MakeLocationSummary() const { | 2147 LocationSummary* UnboxDoubleInstr::MakeLocationSummary() const { |
2147 const intptr_t kNumInputs = 1; | 2148 const intptr_t kNumInputs = 1; |
2148 const intptr_t kNumTemps = CanDeoptimize() ? 1 : 0; | 2149 const intptr_t kNumTemps = CanDeoptimize() ? 1 : 0; |
2149 LocationSummary* summary = | 2150 LocationSummary* summary = |
2150 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2151 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
2151 summary->set_in(0, Location::RequiresRegister()); | 2152 summary->set_in(0, Location::RequiresRegister()); |
2152 if (CanDeoptimize()) summary->set_temp(0, Location::RequiresRegister()); | 2153 if (CanDeoptimize()) summary->set_temp(0, Location::RequiresRegister()); |
2153 summary->set_out(Location::RequiresXmmRegister()); | 2154 summary->set_out(Location::RequiresFpuRegister()); |
2154 return summary; | 2155 return summary; |
2155 } | 2156 } |
2156 | 2157 |
2157 | 2158 |
2158 void UnboxDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2159 void UnboxDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2159 const intptr_t value_cid = value()->ResultCid(); | 2160 const intptr_t value_cid = value()->ResultCid(); |
2160 const Register value = locs()->in(0).reg(); | 2161 const Register value = locs()->in(0).reg(); |
2161 const XmmRegister result = locs()->out().xmm_reg(); | 2162 const XmmRegister result = locs()->out().fpu_reg(); |
2162 | 2163 |
2163 if (value_cid == kDoubleCid) { | 2164 if (value_cid == kDoubleCid) { |
2164 __ movsd(result, FieldAddress(value, Double::value_offset())); | 2165 __ movsd(result, FieldAddress(value, Double::value_offset())); |
2165 } else if (value_cid == kSmiCid) { | 2166 } else if (value_cid == kSmiCid) { |
2166 __ SmiUntag(value); // Untag input before conversion. | 2167 __ SmiUntag(value); // Untag input before conversion. |
2167 __ cvtsi2sd(result, value); | 2168 __ cvtsi2sd(result, value); |
2168 __ SmiTag(value); // Restore input register. | 2169 __ SmiTag(value); // Restore input register. |
2169 } else { | 2170 } else { |
2170 Label* deopt = compiler->AddDeoptStub(deopt_id_, kDeoptBinaryDoubleOp); | 2171 Label* deopt = compiler->AddDeoptStub(deopt_id_, kDeoptBinaryDoubleOp); |
2171 compiler->LoadDoubleOrSmiToXmm(result, | 2172 compiler->LoadDoubleOrSmiToFpu(result, |
2172 value, | 2173 value, |
2173 locs()->temp(0).reg(), | 2174 locs()->temp(0).reg(), |
2174 deopt); | 2175 deopt); |
2175 } | 2176 } |
2176 } | 2177 } |
2177 | 2178 |
2178 | 2179 |
2179 LocationSummary* BinaryDoubleOpInstr::MakeLocationSummary() const { | 2180 LocationSummary* BinaryDoubleOpInstr::MakeLocationSummary() const { |
2180 const intptr_t kNumInputs = 2; | 2181 const intptr_t kNumInputs = 2; |
2181 const intptr_t kNumTemps = 0; | 2182 const intptr_t kNumTemps = 0; |
2182 LocationSummary* summary = | 2183 LocationSummary* summary = |
2183 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2184 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
2184 summary->set_in(0, Location::RequiresXmmRegister()); | 2185 summary->set_in(0, Location::RequiresFpuRegister()); |
2185 summary->set_in(1, Location::RequiresXmmRegister()); | 2186 summary->set_in(1, Location::RequiresFpuRegister()); |
2186 summary->set_out(Location::SameAsFirstInput()); | 2187 summary->set_out(Location::SameAsFirstInput()); |
2187 return summary; | 2188 return summary; |
2188 } | 2189 } |
2189 | 2190 |
2190 | 2191 |
2191 void BinaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2192 void BinaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2192 XmmRegister left = locs()->in(0).xmm_reg(); | 2193 XmmRegister left = locs()->in(0).fpu_reg(); |
2193 XmmRegister right = locs()->in(1).xmm_reg(); | 2194 XmmRegister right = locs()->in(1).fpu_reg(); |
2194 | 2195 |
2195 ASSERT(locs()->out().xmm_reg() == left); | 2196 ASSERT(locs()->out().fpu_reg() == left); |
2196 | 2197 |
2197 switch (op_kind()) { | 2198 switch (op_kind()) { |
2198 case Token::kADD: __ addsd(left, right); break; | 2199 case Token::kADD: __ addsd(left, right); break; |
2199 case Token::kSUB: __ subsd(left, right); break; | 2200 case Token::kSUB: __ subsd(left, right); break; |
2200 case Token::kMUL: __ mulsd(left, right); break; | 2201 case Token::kMUL: __ mulsd(left, right); break; |
2201 case Token::kDIV: __ divsd(left, right); break; | 2202 case Token::kDIV: __ divsd(left, right); break; |
2202 default: UNREACHABLE(); | 2203 default: UNREACHABLE(); |
2203 } | 2204 } |
2204 } | 2205 } |
2205 | 2206 |
2206 | 2207 |
2207 LocationSummary* MathSqrtInstr::MakeLocationSummary() const { | 2208 LocationSummary* MathSqrtInstr::MakeLocationSummary() const { |
2208 const intptr_t kNumInputs = 1; | 2209 const intptr_t kNumInputs = 1; |
2209 const intptr_t kNumTemps = 0; | 2210 const intptr_t kNumTemps = 0; |
2210 LocationSummary* summary = | 2211 LocationSummary* summary = |
2211 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2212 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
2212 summary->set_in(0, Location::RequiresXmmRegister()); | 2213 summary->set_in(0, Location::RequiresFpuRegister()); |
2213 summary->set_out(Location::RequiresXmmRegister()); | 2214 summary->set_out(Location::RequiresFpuRegister()); |
2214 return summary; | 2215 return summary; |
2215 } | 2216 } |
2216 | 2217 |
2217 | 2218 |
2218 void MathSqrtInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2219 void MathSqrtInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2219 __ sqrtsd(locs()->out().xmm_reg(), locs()->in(0).xmm_reg()); | 2220 __ sqrtsd(locs()->out().fpu_reg(), locs()->in(0).fpu_reg()); |
2220 } | 2221 } |
2221 | 2222 |
2222 | 2223 |
2223 LocationSummary* UnarySmiOpInstr::MakeLocationSummary() const { | 2224 LocationSummary* UnarySmiOpInstr::MakeLocationSummary() const { |
2224 const intptr_t kNumInputs = 1; | 2225 const intptr_t kNumInputs = 1; |
2225 const intptr_t kNumTemps = 0; | 2226 const intptr_t kNumTemps = 0; |
2226 LocationSummary* summary = | 2227 LocationSummary* summary = |
2227 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2228 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
2228 summary->set_in(0, Location::RequiresRegister()); | 2229 summary->set_in(0, Location::RequiresRegister()); |
2229 summary->set_out(Location::SameAsFirstInput()); | 2230 summary->set_out(Location::SameAsFirstInput()); |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2329 locs()); | 2330 locs()); |
2330 __ Bind(&done); | 2331 __ Bind(&done); |
2331 } | 2332 } |
2332 | 2333 |
2333 | 2334 |
2334 LocationSummary* DoubleToSmiInstr::MakeLocationSummary() const { | 2335 LocationSummary* DoubleToSmiInstr::MakeLocationSummary() const { |
2335 const intptr_t kNumInputs = 1; | 2336 const intptr_t kNumInputs = 1; |
2336 const intptr_t kNumTemps = 0; | 2337 const intptr_t kNumTemps = 0; |
2337 LocationSummary* result = new LocationSummary( | 2338 LocationSummary* result = new LocationSummary( |
2338 kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2339 kNumInputs, kNumTemps, LocationSummary::kNoCall); |
2339 result->set_in(0, Location::RequiresXmmRegister()); | 2340 result->set_in(0, Location::RequiresFpuRegister()); |
2340 result->set_out(Location::RequiresRegister()); | 2341 result->set_out(Location::RequiresRegister()); |
2341 return result; | 2342 return result; |
2342 } | 2343 } |
2343 | 2344 |
2344 | 2345 |
2345 void DoubleToSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2346 void DoubleToSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2346 Label* deopt = compiler->AddDeoptStub(deopt_id(), kDeoptDoubleToSmi); | 2347 Label* deopt = compiler->AddDeoptStub(deopt_id(), kDeoptDoubleToSmi); |
2347 Register result = locs()->out().reg(); | 2348 Register result = locs()->out().reg(); |
2348 XmmRegister value = locs()->in(0).xmm_reg(); | 2349 XmmRegister value = locs()->in(0).fpu_reg(); |
2349 __ cvttsd2si(result, value); | 2350 __ cvttsd2si(result, value); |
2350 // Overflow is signalled with minint. | 2351 // Overflow is signalled with minint. |
2351 Label do_call, done; | 2352 Label do_call, done; |
2352 // Check for overflow and that it fits into Smi. | 2353 // Check for overflow and that it fits into Smi. |
2353 __ cmpl(result, Immediate(0xC0000000)); | 2354 __ cmpl(result, Immediate(0xC0000000)); |
2354 __ j(NEGATIVE, deopt); | 2355 __ j(NEGATIVE, deopt); |
2355 __ SmiTag(result); | 2356 __ SmiTag(result); |
2356 } | 2357 } |
2357 | 2358 |
2358 | 2359 |
2359 LocationSummary* DoubleToDoubleInstr::MakeLocationSummary() const { | 2360 LocationSummary* DoubleToDoubleInstr::MakeLocationSummary() const { |
2360 const intptr_t kNumInputs = 1; | 2361 const intptr_t kNumInputs = 1; |
2361 const intptr_t kNumTemps = | 2362 const intptr_t kNumTemps = |
2362 (recognized_kind() == MethodRecognizer::kDoubleRound) ? 1 : 0; | 2363 (recognized_kind() == MethodRecognizer::kDoubleRound) ? 1 : 0; |
2363 LocationSummary* result = | 2364 LocationSummary* result = |
2364 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2365 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
2365 result->set_in(0, Location::RequiresXmmRegister()); | 2366 result->set_in(0, Location::RequiresFpuRegister()); |
2366 result->set_out(Location::RequiresXmmRegister()); | 2367 result->set_out(Location::RequiresFpuRegister()); |
2367 if (recognized_kind() == MethodRecognizer::kDoubleRound) { | 2368 if (recognized_kind() == MethodRecognizer::kDoubleRound) { |
2368 result->set_temp(0, Location::RequiresXmmRegister()); | 2369 result->set_temp(0, Location::RequiresFpuRegister()); |
2369 } | 2370 } |
2370 return result; | 2371 return result; |
2371 } | 2372 } |
2372 | 2373 |
2373 | 2374 |
2374 void DoubleToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2375 void DoubleToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2375 XmmRegister value = locs()->in(0).xmm_reg(); | 2376 XmmRegister value = locs()->in(0).fpu_reg(); |
2376 XmmRegister result = locs()->out().xmm_reg(); | 2377 XmmRegister result = locs()->out().fpu_reg(); |
2377 if (recognized_kind() == MethodRecognizer::kDoubleTruncate) { | 2378 if (recognized_kind() == MethodRecognizer::kDoubleTruncate) { |
2378 __ roundsd(result, value, Assembler::kRoundToZero); | 2379 __ roundsd(result, value, Assembler::kRoundToZero); |
2379 } else { | 2380 } else { |
2380 XmmRegister temp = locs()->temp(0).xmm_reg(); | 2381 XmmRegister temp = locs()->temp(0).fpu_reg(); |
2381 __ DoubleRound(result, value, temp); | 2382 __ DoubleRound(result, value, temp); |
2382 } | 2383 } |
2383 } | 2384 } |
2384 | 2385 |
2385 | 2386 |
2386 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary() const { | 2387 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary() const { |
2387 return MakeCallSummary(); | 2388 return MakeCallSummary(); |
2388 } | 2389 } |
2389 | 2390 |
2390 | 2391 |
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2563 } | 2564 } |
2564 | 2565 |
2565 | 2566 |
2566 LocationSummary* UnboxIntegerInstr::MakeLocationSummary() const { | 2567 LocationSummary* UnboxIntegerInstr::MakeLocationSummary() const { |
2567 const intptr_t kNumInputs = 1; | 2568 const intptr_t kNumInputs = 1; |
2568 const intptr_t kNumTemps = CanDeoptimize() ? 1 : 0; | 2569 const intptr_t kNumTemps = CanDeoptimize() ? 1 : 0; |
2569 LocationSummary* summary = | 2570 LocationSummary* summary = |
2570 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2571 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
2571 summary->set_in(0, Location::RequiresRegister()); | 2572 summary->set_in(0, Location::RequiresRegister()); |
2572 if (CanDeoptimize()) summary->set_temp(0, Location::RequiresRegister()); | 2573 if (CanDeoptimize()) summary->set_temp(0, Location::RequiresRegister()); |
2573 summary->set_out(Location::RequiresXmmRegister()); | 2574 summary->set_out(Location::RequiresFpuRegister()); |
2574 return summary; | 2575 return summary; |
2575 } | 2576 } |
2576 | 2577 |
2577 | 2578 |
2578 void UnboxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2579 void UnboxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2579 const intptr_t value_cid = value()->ResultCid(); | 2580 const intptr_t value_cid = value()->ResultCid(); |
2580 const Register value = locs()->in(0).reg(); | 2581 const Register value = locs()->in(0).reg(); |
2581 const XmmRegister result = locs()->out().xmm_reg(); | 2582 const XmmRegister result = locs()->out().fpu_reg(); |
2582 | 2583 |
2583 if (value_cid == kMintCid) { | 2584 if (value_cid == kMintCid) { |
2584 __ movsd(result, FieldAddress(value, Mint::value_offset())); | 2585 __ movsd(result, FieldAddress(value, Mint::value_offset())); |
2585 } else if (value_cid == kSmiCid) { | 2586 } else if (value_cid == kSmiCid) { |
2586 __ SmiUntag(value); // Untag input before conversion. | 2587 __ SmiUntag(value); // Untag input before conversion. |
2587 __ movd(result, value); | 2588 __ movd(result, value); |
2588 __ pmovsxdq(result, result); | 2589 __ pmovsxdq(result, result); |
2589 __ SmiTag(value); // Restore input register. | 2590 __ SmiTag(value); // Restore input register. |
2590 } else { | 2591 } else { |
2591 Register temp = locs()->temp(0).reg(); | 2592 Register temp = locs()->temp(0).reg(); |
(...skipping 15 matching lines...) Expand all Loading... |
2607 } | 2608 } |
2608 | 2609 |
2609 | 2610 |
2610 LocationSummary* BoxIntegerInstr::MakeLocationSummary() const { | 2611 LocationSummary* BoxIntegerInstr::MakeLocationSummary() const { |
2611 const intptr_t kNumInputs = 1; | 2612 const intptr_t kNumInputs = 1; |
2612 const intptr_t kNumTemps = 2; | 2613 const intptr_t kNumTemps = 2; |
2613 LocationSummary* summary = | 2614 LocationSummary* summary = |
2614 new LocationSummary(kNumInputs, | 2615 new LocationSummary(kNumInputs, |
2615 kNumTemps, | 2616 kNumTemps, |
2616 LocationSummary::kCallOnSlowPath); | 2617 LocationSummary::kCallOnSlowPath); |
2617 summary->set_in(0, Location::RequiresXmmRegister()); | 2618 summary->set_in(0, Location::RequiresFpuRegister()); |
2618 summary->set_temp(0, Location::RegisterLocation(EAX)); | 2619 summary->set_temp(0, Location::RegisterLocation(EAX)); |
2619 summary->set_temp(1, Location::RegisterLocation(EDX)); | 2620 summary->set_temp(1, Location::RegisterLocation(EDX)); |
2620 // TODO(fschneider): Save one temp by using result register as a temp. | 2621 // TODO(fschneider): Save one temp by using result register as a temp. |
2621 summary->set_out(Location::RequiresRegister()); | 2622 summary->set_out(Location::RequiresRegister()); |
2622 return summary; | 2623 return summary; |
2623 } | 2624 } |
2624 | 2625 |
2625 | 2626 |
2626 class BoxIntegerSlowPath : public SlowPathCode { | 2627 class BoxIntegerSlowPath : public SlowPathCode { |
2627 public: | 2628 public: |
(...skipping 26 matching lines...) Expand all Loading... |
2654 private: | 2655 private: |
2655 BoxIntegerInstr* instruction_; | 2656 BoxIntegerInstr* instruction_; |
2656 }; | 2657 }; |
2657 | 2658 |
2658 | 2659 |
2659 void BoxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2660 void BoxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2660 BoxIntegerSlowPath* slow_path = new BoxIntegerSlowPath(this); | 2661 BoxIntegerSlowPath* slow_path = new BoxIntegerSlowPath(this); |
2661 compiler->AddSlowPathCode(slow_path); | 2662 compiler->AddSlowPathCode(slow_path); |
2662 | 2663 |
2663 Register out_reg = locs()->out().reg(); | 2664 Register out_reg = locs()->out().reg(); |
2664 XmmRegister value = locs()->in(0).xmm_reg(); | 2665 XmmRegister value = locs()->in(0).fpu_reg(); |
2665 | 2666 |
2666 // Unboxed operations produce smis or mint-sized values. | 2667 // Unboxed operations produce smis or mint-sized values. |
2667 // Check if value fits into a smi. | 2668 // Check if value fits into a smi. |
2668 Label not_smi, done; | 2669 Label not_smi, done; |
2669 __ pextrd(EDX, value, Immediate(1)); // Upper half. | 2670 __ pextrd(EDX, value, Immediate(1)); // Upper half. |
2670 __ pextrd(EAX, value, Immediate(0)); // Lower half. | 2671 __ pextrd(EAX, value, Immediate(0)); // Lower half. |
2671 // 1. Compute (x + -kMinSmi) which has to be in the range | 2672 // 1. Compute (x + -kMinSmi) which has to be in the range |
2672 // 0 .. -kMinSmi+kMaxSmi for x to fit into a smi. | 2673 // 0 .. -kMinSmi+kMaxSmi for x to fit into a smi. |
2673 __ addl(EAX, Immediate(0x40000000)); | 2674 __ addl(EAX, Immediate(0x40000000)); |
2674 __ adcl(EDX, Immediate(0)); | 2675 __ adcl(EDX, Immediate(0)); |
(...skipping 23 matching lines...) Expand all Loading... |
2698 | 2699 |
2699 LocationSummary* BinaryMintOpInstr::MakeLocationSummary() const { | 2700 LocationSummary* BinaryMintOpInstr::MakeLocationSummary() const { |
2700 const intptr_t kNumInputs = 2; | 2701 const intptr_t kNumInputs = 2; |
2701 switch (op_kind()) { | 2702 switch (op_kind()) { |
2702 case Token::kBIT_AND: | 2703 case Token::kBIT_AND: |
2703 case Token::kBIT_OR: | 2704 case Token::kBIT_OR: |
2704 case Token::kBIT_XOR: { | 2705 case Token::kBIT_XOR: { |
2705 const intptr_t kNumTemps = 0; | 2706 const intptr_t kNumTemps = 0; |
2706 LocationSummary* summary = | 2707 LocationSummary* summary = |
2707 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2708 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
2708 summary->set_in(0, Location::RequiresXmmRegister()); | 2709 summary->set_in(0, Location::RequiresFpuRegister()); |
2709 summary->set_in(1, Location::RequiresXmmRegister()); | 2710 summary->set_in(1, Location::RequiresFpuRegister()); |
2710 summary->set_out(Location::SameAsFirstInput()); | 2711 summary->set_out(Location::SameAsFirstInput()); |
2711 return summary; | 2712 return summary; |
2712 } | 2713 } |
2713 case Token::kADD: | 2714 case Token::kADD: |
2714 case Token::kSUB: { | 2715 case Token::kSUB: { |
2715 const intptr_t kNumTemps = 2; | 2716 const intptr_t kNumTemps = 2; |
2716 LocationSummary* summary = | 2717 LocationSummary* summary = |
2717 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2718 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
2718 summary->set_in(0, Location::RequiresXmmRegister()); | 2719 summary->set_in(0, Location::RequiresFpuRegister()); |
2719 summary->set_in(1, Location::RequiresXmmRegister()); | 2720 summary->set_in(1, Location::RequiresFpuRegister()); |
2720 summary->set_temp(0, Location::RequiresRegister()); | 2721 summary->set_temp(0, Location::RequiresRegister()); |
2721 summary->set_temp(1, Location::RequiresRegister()); | 2722 summary->set_temp(1, Location::RequiresRegister()); |
2722 summary->set_out(Location::SameAsFirstInput()); | 2723 summary->set_out(Location::SameAsFirstInput()); |
2723 return summary; | 2724 return summary; |
2724 } | 2725 } |
2725 default: | 2726 default: |
2726 UNREACHABLE(); | 2727 UNREACHABLE(); |
2727 return NULL; | 2728 return NULL; |
2728 } | 2729 } |
2729 } | 2730 } |
2730 | 2731 |
2731 | 2732 |
2732 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2733 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2733 XmmRegister left = locs()->in(0).xmm_reg(); | 2734 XmmRegister left = locs()->in(0).fpu_reg(); |
2734 XmmRegister right = locs()->in(1).xmm_reg(); | 2735 XmmRegister right = locs()->in(1).fpu_reg(); |
2735 | 2736 |
2736 ASSERT(locs()->out().xmm_reg() == left); | 2737 ASSERT(locs()->out().fpu_reg() == left); |
2737 | 2738 |
2738 switch (op_kind()) { | 2739 switch (op_kind()) { |
2739 case Token::kBIT_AND: __ andpd(left, right); break; | 2740 case Token::kBIT_AND: __ andpd(left, right); break; |
2740 case Token::kBIT_OR: __ orpd(left, right); break; | 2741 case Token::kBIT_OR: __ orpd(left, right); break; |
2741 case Token::kBIT_XOR: __ xorpd(left, right); break; | 2742 case Token::kBIT_XOR: __ xorpd(left, right); break; |
2742 case Token::kADD: | 2743 case Token::kADD: |
2743 case Token::kSUB: { | 2744 case Token::kSUB: { |
2744 Register lo = locs()->temp(0).reg(); | 2745 Register lo = locs()->temp(0).reg(); |
2745 Register hi = locs()->temp(1).reg(); | 2746 Register hi = locs()->temp(1).reg(); |
2746 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 2747 Label* deopt = compiler->AddDeoptStub(deopt_id(), |
(...skipping 23 matching lines...) Expand all Loading... |
2770 default: UNREACHABLE(); | 2771 default: UNREACHABLE(); |
2771 } | 2772 } |
2772 } | 2773 } |
2773 | 2774 |
2774 | 2775 |
2775 LocationSummary* ShiftMintOpInstr::MakeLocationSummary() const { | 2776 LocationSummary* ShiftMintOpInstr::MakeLocationSummary() const { |
2776 const intptr_t kNumInputs = 2; | 2777 const intptr_t kNumInputs = 2; |
2777 const intptr_t kNumTemps = op_kind() == Token::kSHL ? 2 : 1; | 2778 const intptr_t kNumTemps = op_kind() == Token::kSHL ? 2 : 1; |
2778 LocationSummary* summary = | 2779 LocationSummary* summary = |
2779 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2780 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
2780 summary->set_in(0, Location::RequiresXmmRegister()); | 2781 summary->set_in(0, Location::RequiresFpuRegister()); |
2781 summary->set_in(1, Location::RegisterLocation(ECX)); | 2782 summary->set_in(1, Location::RegisterLocation(ECX)); |
2782 summary->set_temp(0, Location::RequiresRegister()); | 2783 summary->set_temp(0, Location::RequiresRegister()); |
2783 if (op_kind() == Token::kSHL) { | 2784 if (op_kind() == Token::kSHL) { |
2784 summary->set_temp(1, Location::RequiresRegister()); | 2785 summary->set_temp(1, Location::RequiresRegister()); |
2785 } | 2786 } |
2786 summary->set_out(Location::SameAsFirstInput()); | 2787 summary->set_out(Location::SameAsFirstInput()); |
2787 return summary; | 2788 return summary; |
2788 } | 2789 } |
2789 | 2790 |
2790 | 2791 |
2791 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2792 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2792 XmmRegister left = locs()->in(0).xmm_reg(); | 2793 XmmRegister left = locs()->in(0).fpu_reg(); |
2793 ASSERT(locs()->in(1).reg() == ECX); | 2794 ASSERT(locs()->in(1).reg() == ECX); |
2794 ASSERT(locs()->out().xmm_reg() == left); | 2795 ASSERT(locs()->out().fpu_reg() == left); |
2795 | 2796 |
2796 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 2797 Label* deopt = compiler->AddDeoptStub(deopt_id(), |
2797 kDeoptShiftMintOp); | 2798 kDeoptShiftMintOp); |
2798 Label done; | 2799 Label done; |
2799 __ testl(ECX, ECX); | 2800 __ testl(ECX, ECX); |
2800 __ j(ZERO, &done); // Shift by 0 is a nop. | 2801 __ j(ZERO, &done); // Shift by 0 is a nop. |
2801 __ subl(ESP, Immediate(2 * kWordSize)); | 2802 __ subl(ESP, Immediate(2 * kWordSize)); |
2802 __ movq(Address(ESP, 0), left); | 2803 __ movq(Address(ESP, 0), left); |
2803 // Deoptimize if shift count is > 31. | 2804 // Deoptimize if shift count is > 31. |
2804 // sarl operation masks the count to 5 bits and | 2805 // sarl operation masks the count to 5 bits and |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2840 __ addl(ESP, Immediate(2 * kWordSize)); | 2841 __ addl(ESP, Immediate(2 * kWordSize)); |
2841 __ Bind(&done); | 2842 __ Bind(&done); |
2842 } | 2843 } |
2843 | 2844 |
2844 | 2845 |
2845 LocationSummary* UnaryMintOpInstr::MakeLocationSummary() const { | 2846 LocationSummary* UnaryMintOpInstr::MakeLocationSummary() const { |
2846 const intptr_t kNumInputs = 1; | 2847 const intptr_t kNumInputs = 1; |
2847 const intptr_t kNumTemps = 0; | 2848 const intptr_t kNumTemps = 0; |
2848 LocationSummary* summary = | 2849 LocationSummary* summary = |
2849 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2850 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
2850 summary->set_in(0, Location::RequiresXmmRegister()); | 2851 summary->set_in(0, Location::RequiresFpuRegister()); |
2851 summary->set_out(Location::SameAsFirstInput()); | 2852 summary->set_out(Location::SameAsFirstInput()); |
2852 return summary; | 2853 return summary; |
2853 } | 2854 } |
2854 | 2855 |
2855 | 2856 |
2856 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2857 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2857 ASSERT(op_kind() == Token::kBIT_NOT); | 2858 ASSERT(op_kind() == Token::kBIT_NOT); |
2858 XmmRegister value = locs()->in(0).xmm_reg(); | 2859 XmmRegister value = locs()->in(0).fpu_reg(); |
2859 ASSERT(value == locs()->out().xmm_reg()); | 2860 ASSERT(value == locs()->out().fpu_reg()); |
2860 __ pcmpeqq(XMM0, XMM0); // Generate all 1's. | 2861 __ pcmpeqq(XMM0, XMM0); // Generate all 1's. |
2861 __ pxor(value, XMM0); | 2862 __ pxor(value, XMM0); |
2862 } | 2863 } |
2863 | 2864 |
2864 | 2865 |
| 2866 LocationSummary* ThrowInstr::MakeLocationSummary() const { |
| 2867 return new LocationSummary(0, 0, LocationSummary::kCall); |
| 2868 } |
| 2869 |
| 2870 |
| 2871 |
| 2872 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2873 compiler->GenerateCallRuntime(token_pos(), |
| 2874 kThrowRuntimeEntry, |
| 2875 locs()); |
| 2876 __ int3(); |
| 2877 } |
| 2878 |
| 2879 |
| 2880 LocationSummary* ReThrowInstr::MakeLocationSummary() const { |
| 2881 return new LocationSummary(0, 0, LocationSummary::kCall); |
| 2882 } |
| 2883 |
| 2884 |
| 2885 void ReThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2886 compiler->GenerateCallRuntime(token_pos(), |
| 2887 kReThrowRuntimeEntry, |
| 2888 locs()); |
| 2889 __ int3(); |
| 2890 } |
| 2891 |
| 2892 |
| 2893 LocationSummary* GotoInstr::MakeLocationSummary() const { |
| 2894 return new LocationSummary(0, 0, LocationSummary::kNoCall); |
| 2895 } |
| 2896 |
| 2897 |
| 2898 void GotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2899 // Add deoptimization descriptor for deoptimizing instructions |
| 2900 // that may be inserted before this instruction. |
| 2901 if (!compiler->is_optimizing()) { |
| 2902 compiler->AddCurrentDescriptor(PcDescriptors::kDeoptBefore, |
| 2903 GetDeoptId(), |
| 2904 0); // No token position. |
| 2905 } |
| 2906 |
| 2907 if (HasParallelMove()) { |
| 2908 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); |
| 2909 } |
| 2910 |
| 2911 // We can fall through if the successor is the next block in the list. |
| 2912 // Otherwise, we need a jump. |
| 2913 if (!compiler->IsNextBlock(successor())) { |
| 2914 __ jmp(compiler->GetBlockLabel(successor())); |
| 2915 } |
| 2916 } |
| 2917 |
| 2918 |
| 2919 static Condition NegateCondition(Condition condition) { |
| 2920 switch (condition) { |
| 2921 case EQUAL: return NOT_EQUAL; |
| 2922 case NOT_EQUAL: return EQUAL; |
| 2923 case LESS: return GREATER_EQUAL; |
| 2924 case LESS_EQUAL: return GREATER; |
| 2925 case GREATER: return LESS_EQUAL; |
| 2926 case GREATER_EQUAL: return LESS; |
| 2927 case BELOW: return ABOVE_EQUAL; |
| 2928 case BELOW_EQUAL: return ABOVE; |
| 2929 case ABOVE: return BELOW_EQUAL; |
| 2930 case ABOVE_EQUAL: return BELOW; |
| 2931 default: |
| 2932 OS::Print("Error %d\n", condition); |
| 2933 UNIMPLEMENTED(); |
| 2934 return EQUAL; |
| 2935 } |
| 2936 } |
| 2937 |
| 2938 |
| 2939 void ControlInstruction::EmitBranchOnValue(FlowGraphCompiler* compiler, |
| 2940 bool value) { |
| 2941 if (value && compiler->IsNextBlock(false_successor())) { |
| 2942 __ jmp(compiler->GetBlockLabel(true_successor())); |
| 2943 } else if (!value && compiler->IsNextBlock(true_successor())) { |
| 2944 __ jmp(compiler->GetBlockLabel(false_successor())); |
| 2945 } |
| 2946 } |
| 2947 |
| 2948 |
| 2949 void ControlInstruction::EmitBranchOnCondition(FlowGraphCompiler* compiler, |
| 2950 Condition true_condition) { |
| 2951 if (compiler->IsNextBlock(false_successor())) { |
| 2952 // If the next block is the false successor we will fall through to it. |
| 2953 __ j(true_condition, compiler->GetBlockLabel(true_successor())); |
| 2954 } else { |
| 2955 // If the next block is the true successor we negate comparison and fall |
| 2956 // through to it. |
| 2957 ASSERT(compiler->IsNextBlock(true_successor())); |
| 2958 Condition false_condition = NegateCondition(true_condition); |
| 2959 __ j(false_condition, compiler->GetBlockLabel(false_successor())); |
| 2960 } |
| 2961 } |
| 2962 |
| 2963 |
| 2964 LocationSummary* CurrentContextInstr::MakeLocationSummary() const { |
| 2965 return LocationSummary::Make(0, |
| 2966 Location::RequiresRegister(), |
| 2967 LocationSummary::kNoCall); |
| 2968 } |
| 2969 |
| 2970 |
| 2971 void CurrentContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2972 __ MoveRegister(locs()->out().reg(), CTX); |
| 2973 } |
| 2974 |
| 2975 |
| 2976 LocationSummary* StrictCompareInstr::MakeLocationSummary() const { |
| 2977 const intptr_t kNumInputs = 2; |
| 2978 const intptr_t kNumTemps = 0; |
| 2979 LocationSummary* locs = |
| 2980 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 2981 locs->set_in(0, Location::RegisterOrConstant(left())); |
| 2982 locs->set_in(1, Location::RegisterOrConstant(right())); |
| 2983 locs->set_out(Location::RequiresRegister()); |
| 2984 return locs; |
| 2985 } |
| 2986 |
| 2987 |
| 2988 // Special code for numbers (compare values instead of references.) |
| 2989 void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2990 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); |
| 2991 Location left = locs()->in(0); |
| 2992 Location right = locs()->in(1); |
| 2993 if (left.IsConstant() && right.IsConstant()) { |
| 2994 // TODO(vegorov): should be eliminated earlier by constant propagation. |
| 2995 const bool result = (kind() == Token::kEQ_STRICT) ? |
| 2996 left.constant().raw() == right.constant().raw() : |
| 2997 left.constant().raw() != right.constant().raw(); |
| 2998 __ LoadObject(locs()->out().reg(), result ? Bool::True() : Bool::False()); |
| 2999 return; |
| 3000 } |
| 3001 if (left.IsConstant()) { |
| 3002 compiler->EmitEqualityRegConstCompare(right.reg(), |
| 3003 left.constant(), |
| 3004 needs_number_check()); |
| 3005 } else if (right.IsConstant()) { |
| 3006 compiler->EmitEqualityRegConstCompare(left.reg(), |
| 3007 right.constant(), |
| 3008 needs_number_check()); |
| 3009 } else { |
| 3010 compiler->EmitEqualityRegRegCompare(left.reg(), |
| 3011 right.reg(), |
| 3012 needs_number_check()); |
| 3013 } |
| 3014 |
| 3015 Register result = locs()->out().reg(); |
| 3016 Label load_true, done; |
| 3017 Condition true_condition = (kind() == Token::kEQ_STRICT) ? EQUAL : NOT_EQUAL; |
| 3018 __ j(true_condition, &load_true, Assembler::kNearJump); |
| 3019 __ LoadObject(result, Bool::False()); |
| 3020 __ jmp(&done, Assembler::kNearJump); |
| 3021 __ Bind(&load_true); |
| 3022 __ LoadObject(result, Bool::True()); |
| 3023 __ Bind(&done); |
| 3024 } |
| 3025 |
| 3026 |
| 3027 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 3028 BranchInstr* branch) { |
| 3029 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); |
| 3030 Location left = locs()->in(0); |
| 3031 Location right = locs()->in(1); |
| 3032 if (left.IsConstant() && right.IsConstant()) { |
| 3033 // TODO(vegorov): should be eliminated earlier by constant propagation. |
| 3034 const bool result = (kind() == Token::kEQ_STRICT) ? |
| 3035 left.constant().raw() == right.constant().raw() : |
| 3036 left.constant().raw() != right.constant().raw(); |
| 3037 branch->EmitBranchOnValue(compiler, result); |
| 3038 return; |
| 3039 } |
| 3040 if (left.IsConstant()) { |
| 3041 compiler->EmitEqualityRegConstCompare(right.reg(), |
| 3042 left.constant(), |
| 3043 needs_number_check()); |
| 3044 } else if (right.IsConstant()) { |
| 3045 compiler->EmitEqualityRegConstCompare(left.reg(), |
| 3046 right.constant(), |
| 3047 needs_number_check()); |
| 3048 } else { |
| 3049 compiler->EmitEqualityRegRegCompare(left.reg(), |
| 3050 right.reg(), |
| 3051 needs_number_check()); |
| 3052 } |
| 3053 |
| 3054 Condition true_condition = (kind() == Token::kEQ_STRICT) ? EQUAL : NOT_EQUAL; |
| 3055 branch->EmitBranchOnCondition(compiler, true_condition); |
| 3056 } |
| 3057 |
| 3058 |
| 3059 void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3060 // The arguments to the stub include the closure, as does the arguments |
| 3061 // descriptor. |
| 3062 Register temp_reg = locs()->temp(0).reg(); |
| 3063 int argument_count = ArgumentCount(); |
| 3064 const Array& arguments_descriptor = |
| 3065 Array::ZoneHandle(ArgumentsDescriptor::New(argument_count, |
| 3066 argument_names())); |
| 3067 __ LoadObject(temp_reg, arguments_descriptor); |
| 3068 compiler->GenerateDartCall(deopt_id(), |
| 3069 token_pos(), |
| 3070 &StubCode::CallClosureFunctionLabel(), |
| 3071 PcDescriptors::kOther, |
| 3072 locs()); |
| 3073 __ Drop(argument_count); |
| 3074 } |
| 3075 |
| 3076 |
| 3077 LocationSummary* BooleanNegateInstr::MakeLocationSummary() const { |
| 3078 return LocationSummary::Make(1, |
| 3079 Location::RequiresRegister(), |
| 3080 LocationSummary::kNoCall); |
| 3081 } |
| 3082 |
| 3083 |
| 3084 void BooleanNegateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3085 Register value = locs()->in(0).reg(); |
| 3086 Register result = locs()->out().reg(); |
| 3087 |
| 3088 Label done; |
| 3089 __ LoadObject(result, Bool::True()); |
| 3090 __ CompareRegisters(result, value); |
| 3091 __ j(NOT_EQUAL, &done, Assembler::kNearJump); |
| 3092 __ LoadObject(result, Bool::False()); |
| 3093 __ Bind(&done); |
| 3094 } |
| 3095 |
| 3096 |
| 3097 LocationSummary* ChainContextInstr::MakeLocationSummary() const { |
| 3098 return LocationSummary::Make(1, |
| 3099 Location::NoLocation(), |
| 3100 LocationSummary::kNoCall); |
| 3101 } |
| 3102 |
| 3103 |
| 3104 void ChainContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3105 Register context_value = locs()->in(0).reg(); |
| 3106 |
| 3107 // Chain the new context in context_value to its parent in CTX. |
| 3108 __ StoreIntoObject(context_value, |
| 3109 FieldAddress(context_value, Context::parent_offset()), |
| 3110 CTX); |
| 3111 // Set new context as current context. |
| 3112 __ MoveRegister(CTX, context_value); |
| 3113 } |
| 3114 |
| 3115 |
| 3116 LocationSummary* StoreVMFieldInstr::MakeLocationSummary() const { |
| 3117 const intptr_t kNumInputs = 2; |
| 3118 const intptr_t kNumTemps = 0; |
| 3119 LocationSummary* locs = |
| 3120 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3121 locs->set_in(0, value()->NeedsStoreBuffer() ? Location::WritableRegister() |
| 3122 : Location::RequiresRegister()); |
| 3123 locs->set_in(1, Location::RequiresRegister()); |
| 3124 return locs; |
| 3125 } |
| 3126 |
| 3127 |
| 3128 void StoreVMFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3129 Register value_reg = locs()->in(0).reg(); |
| 3130 Register dest_reg = locs()->in(1).reg(); |
| 3131 |
| 3132 if (value()->NeedsStoreBuffer()) { |
| 3133 __ StoreIntoObject(dest_reg, FieldAddress(dest_reg, offset_in_bytes()), |
| 3134 value_reg); |
| 3135 } else { |
| 3136 __ StoreIntoObjectNoBarrier( |
| 3137 dest_reg, FieldAddress(dest_reg, offset_in_bytes()), value_reg); |
| 3138 } |
| 3139 } |
| 3140 |
| 3141 |
| 3142 LocationSummary* AllocateObjectInstr::MakeLocationSummary() const { |
| 3143 return MakeCallSummary(); |
| 3144 } |
| 3145 |
| 3146 |
| 3147 void AllocateObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3148 const Class& cls = Class::ZoneHandle(constructor().Owner()); |
| 3149 const Code& stub = Code::Handle(StubCode::GetAllocationStubForClass(cls)); |
| 3150 const ExternalLabel label(cls.ToCString(), stub.EntryPoint()); |
| 3151 compiler->GenerateCall(token_pos(), |
| 3152 &label, |
| 3153 PcDescriptors::kOther, |
| 3154 locs()); |
| 3155 __ Drop(ArgumentCount()); // Discard arguments. |
| 3156 } |
| 3157 |
| 3158 |
| 3159 LocationSummary* CreateClosureInstr::MakeLocationSummary() const { |
| 3160 return MakeCallSummary(); |
| 3161 } |
| 3162 |
| 3163 |
| 3164 void CreateClosureInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3165 const Function& closure_function = function(); |
| 3166 ASSERT(!closure_function.IsImplicitStaticClosureFunction()); |
| 3167 const Code& stub = Code::Handle( |
| 3168 StubCode::GetAllocationStubForClosure(closure_function)); |
| 3169 const ExternalLabel label(closure_function.ToCString(), stub.EntryPoint()); |
| 3170 compiler->GenerateCall(token_pos(), |
| 3171 &label, |
| 3172 PcDescriptors::kOther, |
| 3173 locs()); |
| 3174 __ Drop(2); // Discard type arguments and receiver. |
| 3175 } |
| 3176 |
2865 } // namespace dart | 3177 } // namespace dart |
2866 | 3178 |
2867 #undef __ | 3179 #undef __ |
2868 | 3180 |
2869 #endif // defined TARGET_ARCH_X64 | 3181 #endif // defined TARGET_ARCH_IA32 |
OLD | NEW |