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 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
334 const ICData& original_ic_data) { | 335 const ICData& original_ic_data) { |
335 if (!compiler->is_optimizing()) { | 336 if (!compiler->is_optimizing()) { |
336 compiler->AddCurrentDescriptor(PcDescriptors::kDeoptBefore, | 337 compiler->AddCurrentDescriptor(PcDescriptors::kDeoptBefore, |
337 deopt_id, | 338 deopt_id, |
338 token_pos); | 339 token_pos); |
339 } | 340 } |
340 const int kNumberOfArguments = 2; | 341 const int kNumberOfArguments = 2; |
341 const Array& kNoArgumentNames = Array::Handle(); | 342 const Array& kNoArgumentNames = Array::Handle(); |
342 const int kNumArgumentsChecked = 2; | 343 const int kNumArgumentsChecked = 2; |
343 | 344 |
344 const Immediate raw_null = | 345 const Immediate& raw_null = |
345 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 346 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
346 Label check_identity; | 347 Label check_identity; |
347 __ cmpl(Address(ESP, 0 * kWordSize), raw_null); | 348 __ cmpl(Address(ESP, 0 * kWordSize), raw_null); |
348 __ j(EQUAL, &check_identity); | 349 __ j(EQUAL, &check_identity); |
349 __ cmpl(Address(ESP, 1 * kWordSize), raw_null); | 350 __ cmpl(Address(ESP, 1 * kWordSize), raw_null); |
350 __ j(EQUAL, &check_identity); | 351 __ j(EQUAL, &check_identity); |
351 | 352 |
352 ICData& equality_ic_data = ICData::ZoneHandle(); | 353 ICData& equality_ic_data = ICData::ZoneHandle(); |
353 if (compiler->is_optimizing() && FLAG_propagate_ic_data) { | 354 if (compiler->is_optimizing() && FLAG_propagate_ic_data) { |
354 ASSERT(!original_ic_data.IsNull()); | 355 ASSERT(!original_ic_data.IsNull()); |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
520 BranchInstr* branch, | 521 BranchInstr* branch, |
521 intptr_t deopt_id) { | 522 intptr_t deopt_id) { |
522 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); | 523 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); |
523 Register left = locs.in(0).reg(); | 524 Register left = locs.in(0).reg(); |
524 Register right = locs.in(1).reg(); | 525 Register right = locs.in(1).reg(); |
525 Register temp = locs.temp(0).reg(); | 526 Register temp = locs.temp(0).reg(); |
526 Label* deopt = compiler->AddDeoptStub(deopt_id, kDeoptEquality); | 527 Label* deopt = compiler->AddDeoptStub(deopt_id, kDeoptEquality); |
527 __ testl(left, Immediate(kSmiTagMask)); | 528 __ testl(left, Immediate(kSmiTagMask)); |
528 __ j(ZERO, deopt); | 529 __ j(ZERO, deopt); |
529 // 'left' is not Smi. | 530 // 'left' is not Smi. |
530 const Immediate raw_null = | 531 const Immediate& raw_null = |
531 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 532 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
532 Label identity_compare; | 533 Label identity_compare; |
533 __ cmpl(right, raw_null); | 534 __ cmpl(right, raw_null); |
534 __ j(EQUAL, &identity_compare); | 535 __ j(EQUAL, &identity_compare); |
535 __ cmpl(left, raw_null); | 536 __ cmpl(left, raw_null); |
536 __ j(EQUAL, &identity_compare); | 537 __ j(EQUAL, &identity_compare); |
537 | 538 |
538 __ LoadClassId(temp, left); | 539 __ LoadClassId(temp, left); |
539 const intptr_t len = ic_data.NumberOfChecks(); | 540 const intptr_t len = ic_data.NumberOfChecks(); |
540 for (intptr_t i = 0; i < len; i++) { | 541 for (intptr_t i = 0; i < len; i++) { |
(...skipping 30 matching lines...) Expand all Loading... |
571 LocationSummary* locs, | 572 LocationSummary* locs, |
572 Token::Kind kind, | 573 Token::Kind kind, |
573 BranchInstr* branch, | 574 BranchInstr* branch, |
574 const ICData& ic_data, | 575 const ICData& ic_data, |
575 intptr_t deopt_id, | 576 intptr_t deopt_id, |
576 intptr_t token_pos) { | 577 intptr_t token_pos) { |
577 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); | 578 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); |
578 ASSERT(!ic_data.IsNull() && (ic_data.NumberOfChecks() > 0)); | 579 ASSERT(!ic_data.IsNull() && (ic_data.NumberOfChecks() > 0)); |
579 Register left = locs->in(0).reg(); | 580 Register left = locs->in(0).reg(); |
580 Register right = locs->in(1).reg(); | 581 Register right = locs->in(1).reg(); |
581 const Immediate raw_null = | 582 const Immediate& raw_null = |
582 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 583 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
583 Label done, identity_compare, non_null_compare; | 584 Label done, identity_compare, non_null_compare; |
584 __ cmpl(right, raw_null); | 585 __ cmpl(right, raw_null); |
585 __ j(EQUAL, &identity_compare, Assembler::kNearJump); | 586 __ j(EQUAL, &identity_compare, Assembler::kNearJump); |
586 __ cmpl(left, raw_null); | 587 __ cmpl(left, raw_null); |
587 __ j(NOT_EQUAL, &non_null_compare, Assembler::kNearJump); | 588 __ j(NOT_EQUAL, &non_null_compare, Assembler::kNearJump); |
588 // Comparison with NULL is "===". | 589 // Comparison with NULL is "===". |
589 __ Bind(&identity_compare); | 590 __ Bind(&identity_compare); |
590 __ cmpl(left, right); | 591 __ cmpl(left, right); |
591 Condition cond = TokenKindToSmiCondition(kind); | 592 Condition cond = TokenKindToSmiCondition(kind); |
(...skipping 65 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 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1144 LocationSummary* locs = | 1145 LocationSummary* locs = |
1145 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1146 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
1146 locs->set_in(0, Location::RequiresRegister()); | 1147 locs->set_in(0, Location::RequiresRegister()); |
1147 // The smi index is either untagged and tagged again at the end of the | 1148 // The smi index is either untagged and tagged again at the end of the |
1148 // operation (element size == 1), or it is left smi tagged (for all element | 1149 // operation (element size == 1), or it is left smi tagged (for all element |
1149 // sizes > 1). | 1150 // sizes > 1). |
1150 locs->set_in(1, CanBeImmediateIndex(index(), class_id()) | 1151 locs->set_in(1, CanBeImmediateIndex(index(), class_id()) |
1151 ? Location::RegisterOrSmiConstant(index()) | 1152 ? Location::RegisterOrSmiConstant(index()) |
1152 : Location::RequiresRegister()); | 1153 : Location::RequiresRegister()); |
1153 if (representation() == kUnboxedDouble) { | 1154 if (representation() == kUnboxedDouble) { |
1154 locs->set_out(Location::RequiresXmmRegister()); | 1155 locs->set_out(Location::RequiresFpuRegister()); |
1155 } else { | 1156 } else { |
1156 locs->set_out(Location::RequiresRegister()); | 1157 locs->set_out(Location::RequiresRegister()); |
1157 } | 1158 } |
1158 return locs; | 1159 return locs; |
1159 } | 1160 } |
1160 | 1161 |
1161 | 1162 |
1162 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1163 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
1163 Register array = locs()->in(0).reg(); | 1164 Register array = locs()->in(0).reg(); |
1164 Location index = locs()->in(1); | 1165 Location index = locs()->in(1); |
1165 | 1166 |
1166 if (class_id() == kExternalUint8ArrayCid) { | 1167 if (class_id() == kExternalUint8ArrayCid) { |
1167 Register result = locs()->out().reg(); | 1168 Register result = locs()->out().reg(); |
1168 Address element_address = index.IsRegister() | 1169 const Address& element_address = index.IsRegister() |
1169 ? FlowGraphCompiler::ExternalElementAddressForRegIndex( | 1170 ? FlowGraphCompiler::ExternalElementAddressForRegIndex( |
1170 class_id(), result, index.reg()) | 1171 class_id(), result, index.reg()) |
1171 : FlowGraphCompiler::ExternalElementAddressForIntIndex( | 1172 : FlowGraphCompiler::ExternalElementAddressForIntIndex( |
1172 class_id(), result, Smi::Cast(index.constant()).Value()); | 1173 class_id(), result, Smi::Cast(index.constant()).Value()); |
1173 if (index.IsRegister()) { | 1174 if (index.IsRegister()) { |
1174 __ SmiUntag(index.reg()); | 1175 __ SmiUntag(index.reg()); |
1175 } | 1176 } |
1176 __ movl(result, | 1177 __ movl(result, |
1177 FieldAddress(array, ExternalUint8Array::external_data_offset())); | 1178 FieldAddress(array, ExternalUint8Array::external_data_offset())); |
1178 __ movl(result, | 1179 __ movl(result, |
1179 Address(result, ExternalByteArrayData<uint8_t>::data_offset())); | 1180 Address(result, ExternalByteArrayData<uint8_t>::data_offset())); |
1180 __ movzxb(result, element_address); | 1181 __ movzxb(result, element_address); |
1181 __ SmiTag(result); | 1182 __ SmiTag(result); |
1182 if (index.IsRegister()) { | 1183 if (index.IsRegister()) { |
1183 __ SmiTag(index.reg()); // Re-tag. | 1184 __ SmiTag(index.reg()); // Re-tag. |
1184 } | 1185 } |
1185 return; | 1186 return; |
1186 } | 1187 } |
1187 | 1188 |
1188 FieldAddress element_address = index.IsRegister() | 1189 FieldAddress element_address = index.IsRegister() |
1189 ? FlowGraphCompiler::ElementAddressForRegIndex( | 1190 ? FlowGraphCompiler::ElementAddressForRegIndex( |
1190 class_id(), array, index.reg()) | 1191 class_id(), array, index.reg()) |
1191 : FlowGraphCompiler::ElementAddressForIntIndex( | 1192 : FlowGraphCompiler::ElementAddressForIntIndex( |
1192 class_id(), array, Smi::Cast(index.constant()).Value()); | 1193 class_id(), array, Smi::Cast(index.constant()).Value()); |
1193 | 1194 |
1194 if (representation() == kUnboxedDouble) { | 1195 if (representation() == kUnboxedDouble) { |
1195 XmmRegister result = locs()->out().xmm_reg(); | 1196 XmmRegister result = locs()->out().fpu_reg(); |
1196 if (class_id() == kFloat32ArrayCid) { | 1197 if (class_id() == kFloat32ArrayCid) { |
1197 // Load single precision float. | 1198 // Load single precision float. |
1198 __ movss(result, element_address); | 1199 __ movss(result, element_address); |
1199 // Promote to double. | 1200 // Promote to double. |
1200 __ cvtss2sd(result, locs()->out().xmm_reg()); | 1201 __ cvtss2sd(result, locs()->out().fpu_reg()); |
1201 } else { | 1202 } else { |
1202 ASSERT(class_id() == kFloat64ArrayCid); | 1203 ASSERT(class_id() == kFloat64ArrayCid); |
1203 __ movsd(result, element_address); | 1204 __ movsd(result, element_address); |
1204 } | 1205 } |
1205 return; | 1206 return; |
1206 } | 1207 } |
1207 | 1208 |
1208 Register result = locs()->out().reg(); | 1209 Register result = locs()->out().reg(); |
1209 switch (class_id()) { | 1210 switch (class_id()) { |
1210 case kInt8ArrayCid: | 1211 case kInt8ArrayCid: |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1264 // EBX, ECX, EDX) instead of using a fixed register. | 1265 // EBX, ECX, EDX) instead of using a fixed register. |
1265 locs->set_in(2, Location::FixedRegisterOrSmiConstant(value(), EAX)); | 1266 locs->set_in(2, Location::FixedRegisterOrSmiConstant(value(), EAX)); |
1266 break; | 1267 break; |
1267 case kInt16ArrayCid: | 1268 case kInt16ArrayCid: |
1268 case kUint16ArrayCid: | 1269 case kUint16ArrayCid: |
1269 // Writable register because the value must be untagged before storing. | 1270 // Writable register because the value must be untagged before storing. |
1270 locs->set_in(2, Location::WritableRegister()); | 1271 locs->set_in(2, Location::WritableRegister()); |
1271 break; | 1272 break; |
1272 case kFloat32ArrayCid: | 1273 case kFloat32ArrayCid: |
1273 // Need temp register for float-to-double conversion. | 1274 // Need temp register for float-to-double conversion. |
1274 locs->AddTemp(Location::RequiresXmmRegister()); | 1275 locs->AddTemp(Location::RequiresFpuRegister()); |
1275 // Fall through. | 1276 // Fall through. |
1276 case kFloat64ArrayCid: | 1277 case kFloat64ArrayCid: |
1277 // TODO(srdjan): Support Float64 constants. | 1278 // TODO(srdjan): Support Float64 constants. |
1278 locs->set_in(2, Location::RequiresXmmRegister()); | 1279 locs->set_in(2, Location::RequiresFpuRegister()); |
1279 break; | 1280 break; |
1280 default: | 1281 default: |
1281 UNREACHABLE(); | 1282 UNREACHABLE(); |
1282 return NULL; | 1283 return NULL; |
1283 } | 1284 } |
1284 return locs; | 1285 return locs; |
1285 } | 1286 } |
1286 | 1287 |
1287 | 1288 |
1288 void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1289 void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1363 } | 1364 } |
1364 case kInt16ArrayCid: | 1365 case kInt16ArrayCid: |
1365 case kUint16ArrayCid: { | 1366 case kUint16ArrayCid: { |
1366 Register value = locs()->in(2).reg(); | 1367 Register value = locs()->in(2).reg(); |
1367 __ SmiUntag(value); | 1368 __ SmiUntag(value); |
1368 __ movw(element_address, value); | 1369 __ movw(element_address, value); |
1369 break; | 1370 break; |
1370 } | 1371 } |
1371 case kFloat32ArrayCid: | 1372 case kFloat32ArrayCid: |
1372 // Convert to single precision. | 1373 // Convert to single precision. |
1373 __ cvtsd2ss(locs()->temp(0).xmm_reg(), locs()->in(2).xmm_reg()); | 1374 __ cvtsd2ss(locs()->temp(0).fpu_reg(), locs()->in(2).fpu_reg()); |
1374 // Store. | 1375 // Store. |
1375 __ movss(element_address, locs()->temp(0).xmm_reg()); | 1376 __ movss(element_address, locs()->temp(0).fpu_reg()); |
1376 break; | 1377 break; |
1377 case kFloat64ArrayCid: | 1378 case kFloat64ArrayCid: |
1378 __ movsd(element_address, locs()->in(2).xmm_reg()); | 1379 __ movsd(element_address, locs()->in(2).fpu_reg()); |
1379 break; | 1380 break; |
1380 default: | 1381 default: |
1381 UNREACHABLE(); | 1382 UNREACHABLE(); |
1382 } | 1383 } |
1383 } | 1384 } |
1384 | 1385 |
1385 | 1386 |
1386 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary() const { | 1387 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary() const { |
1387 const intptr_t kNumInputs = 2; | 1388 const intptr_t kNumInputs = 2; |
1388 const intptr_t num_temps = 0; | 1389 const intptr_t num_temps = 0; |
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1578 Register result_reg = locs()->out().reg(); | 1579 Register result_reg = locs()->out().reg(); |
1579 | 1580 |
1580 // 'instantiator_reg' is the instantiator AbstractTypeArguments object | 1581 // 'instantiator_reg' is the instantiator AbstractTypeArguments object |
1581 // (or null). | 1582 // (or null). |
1582 // If the instantiator is null and if the type argument vector | 1583 // If the instantiator is null and if the type argument vector |
1583 // instantiated from null becomes a vector of dynamic, then use null as | 1584 // instantiated from null becomes a vector of dynamic, then use null as |
1584 // the type arguments. | 1585 // the type arguments. |
1585 Label type_arguments_instantiated; | 1586 Label type_arguments_instantiated; |
1586 const intptr_t len = type_arguments().Length(); | 1587 const intptr_t len = type_arguments().Length(); |
1587 if (type_arguments().IsRawInstantiatedRaw(len)) { | 1588 if (type_arguments().IsRawInstantiatedRaw(len)) { |
1588 const Immediate raw_null = | 1589 const Immediate& raw_null = |
1589 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 1590 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
1590 __ cmpl(instantiator_reg, raw_null); | 1591 __ cmpl(instantiator_reg, raw_null); |
1591 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); | 1592 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); |
1592 } | 1593 } |
1593 // Instantiate non-null type arguments. | 1594 // Instantiate non-null type arguments. |
1594 if (type_arguments().IsUninstantiatedIdentity()) { | 1595 if (type_arguments().IsUninstantiatedIdentity()) { |
1595 // Check if the instantiator type argument vector is a TypeArguments of a | 1596 // Check if the instantiator type argument vector is a TypeArguments of a |
1596 // matching length and, if so, use it as the instantiated type_arguments. | 1597 // matching length and, if so, use it as the instantiated type_arguments. |
1597 // No need to check the instantiator ('instantiator_reg') for null here, | 1598 // No need to check the instantiator ('instantiator_reg') for null here, |
1598 // because a null instantiator will have the wrong class (Null instead of | 1599 // because a null instantiator will have the wrong class (Null instead of |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1641 Register temp_reg = locs()->temp(0).reg(); | 1642 Register temp_reg = locs()->temp(0).reg(); |
1642 | 1643 |
1643 // instantiator_reg is the instantiator type argument vector, i.e. an | 1644 // instantiator_reg is the instantiator type argument vector, i.e. an |
1644 // AbstractTypeArguments object (or null). | 1645 // AbstractTypeArguments object (or null). |
1645 // If the instantiator is null and if the type argument vector | 1646 // If the instantiator is null and if the type argument vector |
1646 // instantiated from null becomes a vector of dynamic, then use null as | 1647 // instantiated from null becomes a vector of dynamic, then use null as |
1647 // the type arguments. | 1648 // the type arguments. |
1648 Label type_arguments_instantiated; | 1649 Label type_arguments_instantiated; |
1649 const intptr_t len = type_arguments().Length(); | 1650 const intptr_t len = type_arguments().Length(); |
1650 if (type_arguments().IsRawInstantiatedRaw(len)) { | 1651 if (type_arguments().IsRawInstantiatedRaw(len)) { |
1651 const Immediate raw_null = | 1652 const Immediate& raw_null = |
1652 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 1653 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
1653 __ cmpl(instantiator_reg, raw_null); | 1654 __ cmpl(instantiator_reg, raw_null); |
1654 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); | 1655 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); |
1655 } | 1656 } |
1656 // Instantiate non-null type arguments. | 1657 // Instantiate non-null type arguments. |
1657 if (type_arguments().IsUninstantiatedIdentity()) { | 1658 if (type_arguments().IsUninstantiatedIdentity()) { |
1658 // Check if the instantiator type argument vector is a TypeArguments of a | 1659 // Check if the instantiator type argument vector is a TypeArguments of a |
1659 // matching length and, if so, use it as the instantiated type_arguments. | 1660 // matching length and, if so, use it as the instantiated type_arguments. |
1660 // No need to check instantiator_reg for null here, because a null | 1661 // No need to check instantiator_reg for null here, because a null |
1661 // instantiator will have the wrong class (Null instead of TypeArguments). | 1662 // instantiator will have the wrong class (Null instead of TypeArguments). |
1662 Label type_arguments_uninstantiated; | 1663 Label type_arguments_uninstantiated; |
1663 __ CompareClassId(instantiator_reg, kTypeArgumentsCid, temp_reg); | 1664 __ CompareClassId(instantiator_reg, kTypeArgumentsCid, temp_reg); |
1664 __ j(NOT_EQUAL, &type_arguments_uninstantiated, Assembler::kNearJump); | 1665 __ j(NOT_EQUAL, &type_arguments_uninstantiated, Assembler::kNearJump); |
1665 Immediate arguments_length = | 1666 const Immediate& arguments_length = |
1666 Immediate(Smi::RawValue(type_arguments().Length())); | 1667 Immediate(Smi::RawValue(type_arguments().Length())); |
1667 __ cmpl(FieldAddress(instantiator_reg, TypeArguments::length_offset()), | 1668 __ cmpl(FieldAddress(instantiator_reg, TypeArguments::length_offset()), |
1668 arguments_length); | 1669 arguments_length); |
1669 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); | 1670 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); |
1670 __ Bind(&type_arguments_uninstantiated); | 1671 __ Bind(&type_arguments_uninstantiated); |
1671 } | 1672 } |
1672 // In the non-factory case, we rely on the allocation stub to | 1673 // In the non-factory case, we rely on the allocation stub to |
1673 // instantiate the type arguments. | 1674 // instantiate the type arguments. |
1674 __ LoadObject(result_reg, type_arguments()); | 1675 __ LoadObject(result_reg, type_arguments()); |
1675 // result_reg: uninstantiated type arguments. | 1676 // result_reg: uninstantiated type arguments. |
(...skipping 21 matching lines...) Expand all Loading... |
1697 ASSERT(locs()->out().reg() == instantiator_reg); | 1698 ASSERT(locs()->out().reg() == instantiator_reg); |
1698 Register temp_reg = locs()->temp(0).reg(); | 1699 Register temp_reg = locs()->temp(0).reg(); |
1699 | 1700 |
1700 // instantiator_reg is the instantiator AbstractTypeArguments object | 1701 // instantiator_reg is the instantiator AbstractTypeArguments object |
1701 // (or null). If the instantiator is null and if the type argument vector | 1702 // (or null). If the instantiator is null and if the type argument vector |
1702 // instantiated from null becomes a vector of dynamic, then use null as | 1703 // instantiated from null becomes a vector of dynamic, then use null as |
1703 // the type arguments and do not pass the instantiator. | 1704 // the type arguments and do not pass the instantiator. |
1704 Label done; | 1705 Label done; |
1705 const intptr_t len = type_arguments().Length(); | 1706 const intptr_t len = type_arguments().Length(); |
1706 if (type_arguments().IsRawInstantiatedRaw(len)) { | 1707 if (type_arguments().IsRawInstantiatedRaw(len)) { |
1707 const Immediate raw_null = | 1708 const Immediate& raw_null = |
1708 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 1709 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
1709 Label instantiator_not_null; | 1710 Label instantiator_not_null; |
1710 __ cmpl(instantiator_reg, raw_null); | 1711 __ cmpl(instantiator_reg, raw_null); |
1711 __ j(NOT_EQUAL, &instantiator_not_null, Assembler::kNearJump); | 1712 __ j(NOT_EQUAL, &instantiator_not_null, Assembler::kNearJump); |
1712 // Null was used in VisitExtractConstructorTypeArguments as the | 1713 // Null was used in VisitExtractConstructorTypeArguments as the |
1713 // instantiated type arguments, no proper instantiator needed. | 1714 // instantiated type arguments, no proper instantiator needed. |
1714 __ movl(instantiator_reg, | 1715 __ movl(instantiator_reg, |
1715 Immediate(Smi::RawValue(StubCode::kNoInstantiator))); | 1716 Immediate(Smi::RawValue(StubCode::kNoInstantiator))); |
1716 __ jmp(&done); | 1717 __ jmp(&done); |
1717 __ Bind(&instantiator_not_null); | 1718 __ Bind(&instantiator_not_null); |
1718 } | 1719 } |
1719 // Instantiate non-null type arguments. | 1720 // Instantiate non-null type arguments. |
1720 if (type_arguments().IsUninstantiatedIdentity()) { | 1721 if (type_arguments().IsUninstantiatedIdentity()) { |
1721 // TODO(regis): The following emitted code is duplicated in | 1722 // TODO(regis): The following emitted code is duplicated in |
1722 // VisitExtractConstructorTypeArguments above. The reason is that the code | 1723 // VisitExtractConstructorTypeArguments above. The reason is that the code |
1723 // is split between two computations, so that each one produces a | 1724 // is split between two computations, so that each one produces a |
1724 // single value, rather than producing a pair of values. | 1725 // single value, rather than producing a pair of values. |
1725 // If this becomes an issue, we should expose these tests at the IL level. | 1726 // If this becomes an issue, we should expose these tests at the IL level. |
1726 | 1727 |
1727 // Check if the instantiator type argument vector is a TypeArguments of a | 1728 // Check if the instantiator type argument vector is a TypeArguments of a |
1728 // matching length and, if so, use it as the instantiated type_arguments. | 1729 // matching length and, if so, use it as the instantiated type_arguments. |
1729 // No need to check the instantiator (RAX) for null here, because a null | 1730 // No need to check the instantiator (RAX) for null here, because a null |
1730 // instantiator will have the wrong class (Null instead of TypeArguments). | 1731 // instantiator will have the wrong class (Null instead of TypeArguments). |
1731 __ CompareClassId(instantiator_reg, kTypeArgumentsCid, temp_reg); | 1732 __ CompareClassId(instantiator_reg, kTypeArgumentsCid, temp_reg); |
1732 __ j(NOT_EQUAL, &done, Assembler::kNearJump); | 1733 __ j(NOT_EQUAL, &done, Assembler::kNearJump); |
1733 Immediate arguments_length = | 1734 const Immediate& arguments_length = |
1734 Immediate(Smi::RawValue(type_arguments().Length())); | 1735 Immediate(Smi::RawValue(type_arguments().Length())); |
1735 __ cmpl(FieldAddress(instantiator_reg, TypeArguments::length_offset()), | 1736 __ cmpl(FieldAddress(instantiator_reg, TypeArguments::length_offset()), |
1736 arguments_length); | 1737 arguments_length); |
1737 __ j(NOT_EQUAL, &done, Assembler::kNearJump); | 1738 __ j(NOT_EQUAL, &done, Assembler::kNearJump); |
1738 // The instantiator was used in VisitExtractConstructorTypeArguments as the | 1739 // The instantiator was used in VisitExtractConstructorTypeArguments as the |
1739 // instantiated type arguments, no proper instantiator needed. | 1740 // instantiated type arguments, no proper instantiator needed. |
1740 __ movl(instantiator_reg, | 1741 __ movl(instantiator_reg, |
1741 Immediate(Smi::RawValue(StubCode::kNoInstantiator))); | 1742 Immediate(Smi::RawValue(StubCode::kNoInstantiator))); |
1742 } | 1743 } |
1743 __ Bind(&done); | 1744 __ Bind(&done); |
(...skipping 413 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2157 } | 2158 } |
2158 | 2159 |
2159 | 2160 |
2160 LocationSummary* BoxDoubleInstr::MakeLocationSummary() const { | 2161 LocationSummary* BoxDoubleInstr::MakeLocationSummary() const { |
2161 const intptr_t kNumInputs = 1; | 2162 const intptr_t kNumInputs = 1; |
2162 const intptr_t kNumTemps = 0; | 2163 const intptr_t kNumTemps = 0; |
2163 LocationSummary* summary = | 2164 LocationSummary* summary = |
2164 new LocationSummary(kNumInputs, | 2165 new LocationSummary(kNumInputs, |
2165 kNumTemps, | 2166 kNumTemps, |
2166 LocationSummary::kCallOnSlowPath); | 2167 LocationSummary::kCallOnSlowPath); |
2167 summary->set_in(0, Location::RequiresXmmRegister()); | 2168 summary->set_in(0, Location::RequiresFpuRegister()); |
2168 summary->set_out(Location::RequiresRegister()); | 2169 summary->set_out(Location::RequiresRegister()); |
2169 return summary; | 2170 return summary; |
2170 } | 2171 } |
2171 | 2172 |
2172 | 2173 |
2173 class BoxDoubleSlowPath : public SlowPathCode { | 2174 class BoxDoubleSlowPath : public SlowPathCode { |
2174 public: | 2175 public: |
2175 explicit BoxDoubleSlowPath(BoxDoubleInstr* instruction) | 2176 explicit BoxDoubleSlowPath(BoxDoubleInstr* instruction) |
2176 : instruction_(instruction) { } | 2177 : instruction_(instruction) { } |
2177 | 2178 |
(...skipping 22 matching lines...) Expand all Loading... |
2200 private: | 2201 private: |
2201 BoxDoubleInstr* instruction_; | 2202 BoxDoubleInstr* instruction_; |
2202 }; | 2203 }; |
2203 | 2204 |
2204 | 2205 |
2205 void BoxDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2206 void BoxDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2206 BoxDoubleSlowPath* slow_path = new BoxDoubleSlowPath(this); | 2207 BoxDoubleSlowPath* slow_path = new BoxDoubleSlowPath(this); |
2207 compiler->AddSlowPathCode(slow_path); | 2208 compiler->AddSlowPathCode(slow_path); |
2208 | 2209 |
2209 Register out_reg = locs()->out().reg(); | 2210 Register out_reg = locs()->out().reg(); |
2210 XmmRegister value = locs()->in(0).xmm_reg(); | 2211 XmmRegister value = locs()->in(0).fpu_reg(); |
2211 | 2212 |
2212 AssemblerMacros::TryAllocate(compiler->assembler(), | 2213 AssemblerMacros::TryAllocate(compiler->assembler(), |
2213 compiler->double_class(), | 2214 compiler->double_class(), |
2214 slow_path->entry_label(), | 2215 slow_path->entry_label(), |
2215 Assembler::kFarJump, | 2216 Assembler::kFarJump, |
2216 out_reg); | 2217 out_reg); |
2217 __ Bind(slow_path->exit_label()); | 2218 __ Bind(slow_path->exit_label()); |
2218 __ movsd(FieldAddress(out_reg, Double::value_offset()), value); | 2219 __ movsd(FieldAddress(out_reg, Double::value_offset()), value); |
2219 } | 2220 } |
2220 | 2221 |
2221 | 2222 |
2222 LocationSummary* UnboxDoubleInstr::MakeLocationSummary() const { | 2223 LocationSummary* UnboxDoubleInstr::MakeLocationSummary() const { |
2223 const intptr_t kNumInputs = 1; | 2224 const intptr_t kNumInputs = 1; |
2224 const intptr_t kNumTemps = CanDeoptimize() ? 1 : 0; | 2225 const intptr_t kNumTemps = CanDeoptimize() ? 1 : 0; |
2225 LocationSummary* summary = | 2226 LocationSummary* summary = |
2226 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2227 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
2227 summary->set_in(0, Location::RequiresRegister()); | 2228 summary->set_in(0, Location::RequiresRegister()); |
2228 if (CanDeoptimize()) summary->set_temp(0, Location::RequiresRegister()); | 2229 if (CanDeoptimize()) summary->set_temp(0, Location::RequiresRegister()); |
2229 summary->set_out(Location::RequiresXmmRegister()); | 2230 summary->set_out(Location::RequiresFpuRegister()); |
2230 return summary; | 2231 return summary; |
2231 } | 2232 } |
2232 | 2233 |
2233 | 2234 |
2234 void UnboxDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2235 void UnboxDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2235 const intptr_t value_cid = value()->ResultCid(); | 2236 const intptr_t value_cid = value()->ResultCid(); |
2236 const Register value = locs()->in(0).reg(); | 2237 const Register value = locs()->in(0).reg(); |
2237 const XmmRegister result = locs()->out().xmm_reg(); | 2238 const XmmRegister result = locs()->out().fpu_reg(); |
2238 | 2239 |
2239 if (value_cid == kDoubleCid) { | 2240 if (value_cid == kDoubleCid) { |
2240 __ movsd(result, FieldAddress(value, Double::value_offset())); | 2241 __ movsd(result, FieldAddress(value, Double::value_offset())); |
2241 } else if (value_cid == kSmiCid) { | 2242 } else if (value_cid == kSmiCid) { |
2242 __ SmiUntag(value); // Untag input before conversion. | 2243 __ SmiUntag(value); // Untag input before conversion. |
2243 __ cvtsi2sd(result, value); | 2244 __ cvtsi2sd(result, value); |
2244 __ SmiTag(value); // Restore input register. | 2245 __ SmiTag(value); // Restore input register. |
2245 } else { | 2246 } else { |
2246 Label* deopt = compiler->AddDeoptStub(deopt_id_, kDeoptBinaryDoubleOp); | 2247 Label* deopt = compiler->AddDeoptStub(deopt_id_, kDeoptBinaryDoubleOp); |
2247 compiler->LoadDoubleOrSmiToXmm(result, | 2248 compiler->LoadDoubleOrSmiToFpu(result, |
2248 value, | 2249 value, |
2249 locs()->temp(0).reg(), | 2250 locs()->temp(0).reg(), |
2250 deopt); | 2251 deopt); |
2251 } | 2252 } |
2252 } | 2253 } |
2253 | 2254 |
2254 | 2255 |
2255 LocationSummary* BinaryDoubleOpInstr::MakeLocationSummary() const { | 2256 LocationSummary* BinaryDoubleOpInstr::MakeLocationSummary() const { |
2256 const intptr_t kNumInputs = 2; | 2257 const intptr_t kNumInputs = 2; |
2257 const intptr_t kNumTemps = 0; | 2258 const intptr_t kNumTemps = 0; |
2258 LocationSummary* summary = | 2259 LocationSummary* summary = |
2259 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2260 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
2260 summary->set_in(0, Location::RequiresXmmRegister()); | 2261 summary->set_in(0, Location::RequiresFpuRegister()); |
2261 summary->set_in(1, Location::RequiresXmmRegister()); | 2262 summary->set_in(1, Location::RequiresFpuRegister()); |
2262 summary->set_out(Location::SameAsFirstInput()); | 2263 summary->set_out(Location::SameAsFirstInput()); |
2263 return summary; | 2264 return summary; |
2264 } | 2265 } |
2265 | 2266 |
2266 | 2267 |
2267 void BinaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2268 void BinaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2268 XmmRegister left = locs()->in(0).xmm_reg(); | 2269 XmmRegister left = locs()->in(0).fpu_reg(); |
2269 XmmRegister right = locs()->in(1).xmm_reg(); | 2270 XmmRegister right = locs()->in(1).fpu_reg(); |
2270 | 2271 |
2271 ASSERT(locs()->out().xmm_reg() == left); | 2272 ASSERT(locs()->out().fpu_reg() == left); |
2272 | 2273 |
2273 switch (op_kind()) { | 2274 switch (op_kind()) { |
2274 case Token::kADD: __ addsd(left, right); break; | 2275 case Token::kADD: __ addsd(left, right); break; |
2275 case Token::kSUB: __ subsd(left, right); break; | 2276 case Token::kSUB: __ subsd(left, right); break; |
2276 case Token::kMUL: __ mulsd(left, right); break; | 2277 case Token::kMUL: __ mulsd(left, right); break; |
2277 case Token::kDIV: __ divsd(left, right); break; | 2278 case Token::kDIV: __ divsd(left, right); break; |
2278 default: UNREACHABLE(); | 2279 default: UNREACHABLE(); |
2279 } | 2280 } |
2280 } | 2281 } |
2281 | 2282 |
2282 | 2283 |
2283 LocationSummary* MathSqrtInstr::MakeLocationSummary() const { | 2284 LocationSummary* MathSqrtInstr::MakeLocationSummary() const { |
2284 const intptr_t kNumInputs = 1; | 2285 const intptr_t kNumInputs = 1; |
2285 const intptr_t kNumTemps = 0; | 2286 const intptr_t kNumTemps = 0; |
2286 LocationSummary* summary = | 2287 LocationSummary* summary = |
2287 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2288 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
2288 summary->set_in(0, Location::RequiresXmmRegister()); | 2289 summary->set_in(0, Location::RequiresFpuRegister()); |
2289 summary->set_out(Location::RequiresXmmRegister()); | 2290 summary->set_out(Location::RequiresFpuRegister()); |
2290 return summary; | 2291 return summary; |
2291 } | 2292 } |
2292 | 2293 |
2293 | 2294 |
2294 void MathSqrtInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2295 void MathSqrtInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2295 __ sqrtsd(locs()->out().xmm_reg(), locs()->in(0).xmm_reg()); | 2296 __ sqrtsd(locs()->out().fpu_reg(), locs()->in(0).fpu_reg()); |
2296 } | 2297 } |
2297 | 2298 |
2298 | 2299 |
2299 LocationSummary* UnarySmiOpInstr::MakeLocationSummary() const { | 2300 LocationSummary* UnarySmiOpInstr::MakeLocationSummary() const { |
2300 const intptr_t kNumInputs = 1; | 2301 const intptr_t kNumInputs = 1; |
2301 const intptr_t kNumTemps = 0; | 2302 const intptr_t kNumTemps = 0; |
2302 LocationSummary* summary = | 2303 LocationSummary* summary = |
2303 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2304 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
2304 summary->set_in(0, Location::RequiresRegister()); | 2305 summary->set_in(0, Location::RequiresRegister()); |
2305 summary->set_out(Location::SameAsFirstInput()); | 2306 summary->set_out(Location::SameAsFirstInput()); |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2405 locs()); | 2406 locs()); |
2406 __ Bind(&done); | 2407 __ Bind(&done); |
2407 } | 2408 } |
2408 | 2409 |
2409 | 2410 |
2410 LocationSummary* DoubleToSmiInstr::MakeLocationSummary() const { | 2411 LocationSummary* DoubleToSmiInstr::MakeLocationSummary() const { |
2411 const intptr_t kNumInputs = 1; | 2412 const intptr_t kNumInputs = 1; |
2412 const intptr_t kNumTemps = 0; | 2413 const intptr_t kNumTemps = 0; |
2413 LocationSummary* result = new LocationSummary( | 2414 LocationSummary* result = new LocationSummary( |
2414 kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2415 kNumInputs, kNumTemps, LocationSummary::kNoCall); |
2415 result->set_in(0, Location::RequiresXmmRegister()); | 2416 result->set_in(0, Location::RequiresFpuRegister()); |
2416 result->set_out(Location::RequiresRegister()); | 2417 result->set_out(Location::RequiresRegister()); |
2417 return result; | 2418 return result; |
2418 } | 2419 } |
2419 | 2420 |
2420 | 2421 |
2421 void DoubleToSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2422 void DoubleToSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2422 Label* deopt = compiler->AddDeoptStub(deopt_id(), kDeoptDoubleToSmi); | 2423 Label* deopt = compiler->AddDeoptStub(deopt_id(), kDeoptDoubleToSmi); |
2423 Register result = locs()->out().reg(); | 2424 Register result = locs()->out().reg(); |
2424 XmmRegister value = locs()->in(0).xmm_reg(); | 2425 XmmRegister value = locs()->in(0).fpu_reg(); |
2425 __ cvttsd2si(result, value); | 2426 __ cvttsd2si(result, value); |
2426 // Overflow is signalled with minint. | 2427 // Overflow is signalled with minint. |
2427 Label do_call, done; | 2428 Label do_call, done; |
2428 // Check for overflow and that it fits into Smi. | 2429 // Check for overflow and that it fits into Smi. |
2429 __ cmpl(result, Immediate(0xC0000000)); | 2430 __ cmpl(result, Immediate(0xC0000000)); |
2430 __ j(NEGATIVE, deopt); | 2431 __ j(NEGATIVE, deopt); |
2431 __ SmiTag(result); | 2432 __ SmiTag(result); |
2432 } | 2433 } |
2433 | 2434 |
2434 | 2435 |
2435 LocationSummary* DoubleToDoubleInstr::MakeLocationSummary() const { | 2436 LocationSummary* DoubleToDoubleInstr::MakeLocationSummary() const { |
2436 const intptr_t kNumInputs = 1; | 2437 const intptr_t kNumInputs = 1; |
2437 const intptr_t kNumTemps = | 2438 const intptr_t kNumTemps = |
2438 (recognized_kind() == MethodRecognizer::kDoubleRound) ? 1 : 0; | 2439 (recognized_kind() == MethodRecognizer::kDoubleRound) ? 1 : 0; |
2439 LocationSummary* result = | 2440 LocationSummary* result = |
2440 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2441 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
2441 result->set_in(0, Location::RequiresXmmRegister()); | 2442 result->set_in(0, Location::RequiresFpuRegister()); |
2442 result->set_out(Location::RequiresXmmRegister()); | 2443 result->set_out(Location::RequiresFpuRegister()); |
2443 if (recognized_kind() == MethodRecognizer::kDoubleRound) { | 2444 if (recognized_kind() == MethodRecognizer::kDoubleRound) { |
2444 result->set_temp(0, Location::RequiresXmmRegister()); | 2445 result->set_temp(0, Location::RequiresFpuRegister()); |
2445 } | 2446 } |
2446 return result; | 2447 return result; |
2447 } | 2448 } |
2448 | 2449 |
2449 | 2450 |
2450 void DoubleToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2451 void DoubleToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2451 XmmRegister value = locs()->in(0).xmm_reg(); | 2452 XmmRegister value = locs()->in(0).fpu_reg(); |
2452 XmmRegister result = locs()->out().xmm_reg(); | 2453 XmmRegister result = locs()->out().fpu_reg(); |
2453 if (recognized_kind() == MethodRecognizer::kDoubleTruncate) { | 2454 if (recognized_kind() == MethodRecognizer::kDoubleTruncate) { |
2454 __ roundsd(result, value, Assembler::kRoundToZero); | 2455 __ roundsd(result, value, Assembler::kRoundToZero); |
2455 } else { | 2456 } else { |
2456 XmmRegister temp = locs()->temp(0).xmm_reg(); | 2457 XmmRegister temp = locs()->temp(0).fpu_reg(); |
2457 __ DoubleRound(result, value, temp); | 2458 __ DoubleRound(result, value, temp); |
2458 } | 2459 } |
2459 } | 2460 } |
2460 | 2461 |
2461 | 2462 |
2462 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary() const { | 2463 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary() const { |
2463 return MakeCallSummary(); | 2464 return MakeCallSummary(); |
2464 } | 2465 } |
2465 | 2466 |
2466 | 2467 |
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2639 } | 2640 } |
2640 | 2641 |
2641 | 2642 |
2642 LocationSummary* UnboxIntegerInstr::MakeLocationSummary() const { | 2643 LocationSummary* UnboxIntegerInstr::MakeLocationSummary() const { |
2643 const intptr_t kNumInputs = 1; | 2644 const intptr_t kNumInputs = 1; |
2644 const intptr_t kNumTemps = CanDeoptimize() ? 1 : 0; | 2645 const intptr_t kNumTemps = CanDeoptimize() ? 1 : 0; |
2645 LocationSummary* summary = | 2646 LocationSummary* summary = |
2646 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2647 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
2647 summary->set_in(0, Location::RequiresRegister()); | 2648 summary->set_in(0, Location::RequiresRegister()); |
2648 if (CanDeoptimize()) summary->set_temp(0, Location::RequiresRegister()); | 2649 if (CanDeoptimize()) summary->set_temp(0, Location::RequiresRegister()); |
2649 summary->set_out(Location::RequiresXmmRegister()); | 2650 summary->set_out(Location::RequiresFpuRegister()); |
2650 return summary; | 2651 return summary; |
2651 } | 2652 } |
2652 | 2653 |
2653 | 2654 |
2654 void UnboxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2655 void UnboxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2655 const intptr_t value_cid = value()->ResultCid(); | 2656 const intptr_t value_cid = value()->ResultCid(); |
2656 const Register value = locs()->in(0).reg(); | 2657 const Register value = locs()->in(0).reg(); |
2657 const XmmRegister result = locs()->out().xmm_reg(); | 2658 const XmmRegister result = locs()->out().fpu_reg(); |
2658 | 2659 |
2659 if (value_cid == kMintCid) { | 2660 if (value_cid == kMintCid) { |
2660 __ movsd(result, FieldAddress(value, Mint::value_offset())); | 2661 __ movsd(result, FieldAddress(value, Mint::value_offset())); |
2661 } else if (value_cid == kSmiCid) { | 2662 } else if (value_cid == kSmiCid) { |
2662 __ SmiUntag(value); // Untag input before conversion. | 2663 __ SmiUntag(value); // Untag input before conversion. |
2663 __ movd(result, value); | 2664 __ movd(result, value); |
2664 __ pmovsxdq(result, result); | 2665 __ pmovsxdq(result, result); |
2665 __ SmiTag(value); // Restore input register. | 2666 __ SmiTag(value); // Restore input register. |
2666 } else { | 2667 } else { |
2667 Register temp = locs()->temp(0).reg(); | 2668 Register temp = locs()->temp(0).reg(); |
(...skipping 15 matching lines...) Expand all Loading... |
2683 } | 2684 } |
2684 | 2685 |
2685 | 2686 |
2686 LocationSummary* BoxIntegerInstr::MakeLocationSummary() const { | 2687 LocationSummary* BoxIntegerInstr::MakeLocationSummary() const { |
2687 const intptr_t kNumInputs = 1; | 2688 const intptr_t kNumInputs = 1; |
2688 const intptr_t kNumTemps = 2; | 2689 const intptr_t kNumTemps = 2; |
2689 LocationSummary* summary = | 2690 LocationSummary* summary = |
2690 new LocationSummary(kNumInputs, | 2691 new LocationSummary(kNumInputs, |
2691 kNumTemps, | 2692 kNumTemps, |
2692 LocationSummary::kCallOnSlowPath); | 2693 LocationSummary::kCallOnSlowPath); |
2693 summary->set_in(0, Location::RequiresXmmRegister()); | 2694 summary->set_in(0, Location::RequiresFpuRegister()); |
2694 summary->set_temp(0, Location::RegisterLocation(EAX)); | 2695 summary->set_temp(0, Location::RegisterLocation(EAX)); |
2695 summary->set_temp(1, Location::RegisterLocation(EDX)); | 2696 summary->set_temp(1, Location::RegisterLocation(EDX)); |
2696 // TODO(fschneider): Save one temp by using result register as a temp. | 2697 // TODO(fschneider): Save one temp by using result register as a temp. |
2697 summary->set_out(Location::RequiresRegister()); | 2698 summary->set_out(Location::RequiresRegister()); |
2698 return summary; | 2699 return summary; |
2699 } | 2700 } |
2700 | 2701 |
2701 | 2702 |
2702 class BoxIntegerSlowPath : public SlowPathCode { | 2703 class BoxIntegerSlowPath : public SlowPathCode { |
2703 public: | 2704 public: |
(...skipping 26 matching lines...) Expand all Loading... |
2730 private: | 2731 private: |
2731 BoxIntegerInstr* instruction_; | 2732 BoxIntegerInstr* instruction_; |
2732 }; | 2733 }; |
2733 | 2734 |
2734 | 2735 |
2735 void BoxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2736 void BoxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2736 BoxIntegerSlowPath* slow_path = new BoxIntegerSlowPath(this); | 2737 BoxIntegerSlowPath* slow_path = new BoxIntegerSlowPath(this); |
2737 compiler->AddSlowPathCode(slow_path); | 2738 compiler->AddSlowPathCode(slow_path); |
2738 | 2739 |
2739 Register out_reg = locs()->out().reg(); | 2740 Register out_reg = locs()->out().reg(); |
2740 XmmRegister value = locs()->in(0).xmm_reg(); | 2741 XmmRegister value = locs()->in(0).fpu_reg(); |
2741 | 2742 |
2742 // Unboxed operations produce smis or mint-sized values. | 2743 // Unboxed operations produce smis or mint-sized values. |
2743 // Check if value fits into a smi. | 2744 // Check if value fits into a smi. |
2744 Label not_smi, done; | 2745 Label not_smi, done; |
2745 __ pextrd(EDX, value, Immediate(1)); // Upper half. | 2746 __ pextrd(EDX, value, Immediate(1)); // Upper half. |
2746 __ pextrd(EAX, value, Immediate(0)); // Lower half. | 2747 __ pextrd(EAX, value, Immediate(0)); // Lower half. |
2747 // 1. Compute (x + -kMinSmi) which has to be in the range | 2748 // 1. Compute (x + -kMinSmi) which has to be in the range |
2748 // 0 .. -kMinSmi+kMaxSmi for x to fit into a smi. | 2749 // 0 .. -kMinSmi+kMaxSmi for x to fit into a smi. |
2749 __ addl(EAX, Immediate(0x40000000)); | 2750 __ addl(EAX, Immediate(0x40000000)); |
2750 __ adcl(EDX, Immediate(0)); | 2751 __ adcl(EDX, Immediate(0)); |
(...skipping 23 matching lines...) Expand all Loading... |
2774 | 2775 |
2775 LocationSummary* BinaryMintOpInstr::MakeLocationSummary() const { | 2776 LocationSummary* BinaryMintOpInstr::MakeLocationSummary() const { |
2776 const intptr_t kNumInputs = 2; | 2777 const intptr_t kNumInputs = 2; |
2777 switch (op_kind()) { | 2778 switch (op_kind()) { |
2778 case Token::kBIT_AND: | 2779 case Token::kBIT_AND: |
2779 case Token::kBIT_OR: | 2780 case Token::kBIT_OR: |
2780 case Token::kBIT_XOR: { | 2781 case Token::kBIT_XOR: { |
2781 const intptr_t kNumTemps = 0; | 2782 const intptr_t kNumTemps = 0; |
2782 LocationSummary* summary = | 2783 LocationSummary* summary = |
2783 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2784 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
2784 summary->set_in(0, Location::RequiresXmmRegister()); | 2785 summary->set_in(0, Location::RequiresFpuRegister()); |
2785 summary->set_in(1, Location::RequiresXmmRegister()); | 2786 summary->set_in(1, Location::RequiresFpuRegister()); |
2786 summary->set_out(Location::SameAsFirstInput()); | 2787 summary->set_out(Location::SameAsFirstInput()); |
2787 return summary; | 2788 return summary; |
2788 } | 2789 } |
2789 case Token::kADD: | 2790 case Token::kADD: |
2790 case Token::kSUB: { | 2791 case Token::kSUB: { |
2791 const intptr_t kNumTemps = 2; | 2792 const intptr_t kNumTemps = 2; |
2792 LocationSummary* summary = | 2793 LocationSummary* summary = |
2793 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2794 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
2794 summary->set_in(0, Location::RequiresXmmRegister()); | 2795 summary->set_in(0, Location::RequiresFpuRegister()); |
2795 summary->set_in(1, Location::RequiresXmmRegister()); | 2796 summary->set_in(1, Location::RequiresFpuRegister()); |
2796 summary->set_temp(0, Location::RequiresRegister()); | 2797 summary->set_temp(0, Location::RequiresRegister()); |
2797 summary->set_temp(1, Location::RequiresRegister()); | 2798 summary->set_temp(1, Location::RequiresRegister()); |
2798 summary->set_out(Location::SameAsFirstInput()); | 2799 summary->set_out(Location::SameAsFirstInput()); |
2799 return summary; | 2800 return summary; |
2800 } | 2801 } |
2801 default: | 2802 default: |
2802 UNREACHABLE(); | 2803 UNREACHABLE(); |
2803 return NULL; | 2804 return NULL; |
2804 } | 2805 } |
2805 } | 2806 } |
2806 | 2807 |
2807 | 2808 |
2808 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2809 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2809 XmmRegister left = locs()->in(0).xmm_reg(); | 2810 XmmRegister left = locs()->in(0).fpu_reg(); |
2810 XmmRegister right = locs()->in(1).xmm_reg(); | 2811 XmmRegister right = locs()->in(1).fpu_reg(); |
2811 | 2812 |
2812 ASSERT(locs()->out().xmm_reg() == left); | 2813 ASSERT(locs()->out().fpu_reg() == left); |
2813 | 2814 |
2814 switch (op_kind()) { | 2815 switch (op_kind()) { |
2815 case Token::kBIT_AND: __ andpd(left, right); break; | 2816 case Token::kBIT_AND: __ andpd(left, right); break; |
2816 case Token::kBIT_OR: __ orpd(left, right); break; | 2817 case Token::kBIT_OR: __ orpd(left, right); break; |
2817 case Token::kBIT_XOR: __ xorpd(left, right); break; | 2818 case Token::kBIT_XOR: __ xorpd(left, right); break; |
2818 case Token::kADD: | 2819 case Token::kADD: |
2819 case Token::kSUB: { | 2820 case Token::kSUB: { |
2820 Register lo = locs()->temp(0).reg(); | 2821 Register lo = locs()->temp(0).reg(); |
2821 Register hi = locs()->temp(1).reg(); | 2822 Register hi = locs()->temp(1).reg(); |
2822 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 2823 Label* deopt = compiler->AddDeoptStub(deopt_id(), |
(...skipping 23 matching lines...) Expand all Loading... |
2846 default: UNREACHABLE(); | 2847 default: UNREACHABLE(); |
2847 } | 2848 } |
2848 } | 2849 } |
2849 | 2850 |
2850 | 2851 |
2851 LocationSummary* ShiftMintOpInstr::MakeLocationSummary() const { | 2852 LocationSummary* ShiftMintOpInstr::MakeLocationSummary() const { |
2852 const intptr_t kNumInputs = 2; | 2853 const intptr_t kNumInputs = 2; |
2853 const intptr_t kNumTemps = op_kind() == Token::kSHL ? 2 : 1; | 2854 const intptr_t kNumTemps = op_kind() == Token::kSHL ? 2 : 1; |
2854 LocationSummary* summary = | 2855 LocationSummary* summary = |
2855 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2856 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
2856 summary->set_in(0, Location::RequiresXmmRegister()); | 2857 summary->set_in(0, Location::RequiresFpuRegister()); |
2857 summary->set_in(1, Location::RegisterLocation(ECX)); | 2858 summary->set_in(1, Location::RegisterLocation(ECX)); |
2858 summary->set_temp(0, Location::RequiresRegister()); | 2859 summary->set_temp(0, Location::RequiresRegister()); |
2859 if (op_kind() == Token::kSHL) { | 2860 if (op_kind() == Token::kSHL) { |
2860 summary->set_temp(1, Location::RequiresRegister()); | 2861 summary->set_temp(1, Location::RequiresRegister()); |
2861 } | 2862 } |
2862 summary->set_out(Location::SameAsFirstInput()); | 2863 summary->set_out(Location::SameAsFirstInput()); |
2863 return summary; | 2864 return summary; |
2864 } | 2865 } |
2865 | 2866 |
2866 | 2867 |
2867 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2868 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2868 XmmRegister left = locs()->in(0).xmm_reg(); | 2869 XmmRegister left = locs()->in(0).fpu_reg(); |
2869 ASSERT(locs()->in(1).reg() == ECX); | 2870 ASSERT(locs()->in(1).reg() == ECX); |
2870 ASSERT(locs()->out().xmm_reg() == left); | 2871 ASSERT(locs()->out().fpu_reg() == left); |
2871 | 2872 |
2872 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 2873 Label* deopt = compiler->AddDeoptStub(deopt_id(), |
2873 kDeoptShiftMintOp); | 2874 kDeoptShiftMintOp); |
2874 Label done; | 2875 Label done; |
2875 __ testl(ECX, ECX); | 2876 __ testl(ECX, ECX); |
2876 __ j(ZERO, &done); // Shift by 0 is a nop. | 2877 __ j(ZERO, &done); // Shift by 0 is a nop. |
2877 __ subl(ESP, Immediate(2 * kWordSize)); | 2878 __ subl(ESP, Immediate(2 * kWordSize)); |
2878 __ movq(Address(ESP, 0), left); | 2879 __ movq(Address(ESP, 0), left); |
2879 // Deoptimize if shift count is > 31. | 2880 // Deoptimize if shift count is > 31. |
2880 // sarl operation masks the count to 5 bits and | 2881 // sarl operation masks the count to 5 bits and |
2881 // shrd is undefined with count > operand size (32) | 2882 // shrd is undefined with count > operand size (32) |
2882 // TODO(fschneider): Support shift counts > 31 without deoptimization. | 2883 // TODO(fschneider): Support shift counts > 31 without deoptimization. |
2883 __ SmiUntag(ECX); | 2884 __ SmiUntag(ECX); |
2884 const Immediate kCountLimit = Immediate(31); | 2885 const Immediate& kCountLimit = Immediate(31); |
2885 __ cmpl(ECX, kCountLimit); | 2886 __ cmpl(ECX, kCountLimit); |
2886 __ j(ABOVE, deopt); | 2887 __ j(ABOVE, deopt); |
2887 switch (op_kind()) { | 2888 switch (op_kind()) { |
2888 case Token::kSHR: { | 2889 case Token::kSHR: { |
2889 Register temp = locs()->temp(0).reg(); | 2890 Register temp = locs()->temp(0).reg(); |
2890 __ movl(temp, Address(ESP, 1 * kWordSize)); // High half. | 2891 __ movl(temp, Address(ESP, 1 * kWordSize)); // High half. |
2891 __ shrd(Address(ESP, 0), temp); // Shift count in CL. | 2892 __ shrd(Address(ESP, 0), temp); // Shift count in CL. |
2892 __ sarl(Address(ESP, 1 * kWordSize), ECX); // Shift count in CL. | 2893 __ sarl(Address(ESP, 1 * kWordSize), ECX); // Shift count in CL. |
2893 break; | 2894 break; |
2894 } | 2895 } |
(...skipping 21 matching lines...) Expand all Loading... |
2916 __ addl(ESP, Immediate(2 * kWordSize)); | 2917 __ addl(ESP, Immediate(2 * kWordSize)); |
2917 __ Bind(&done); | 2918 __ Bind(&done); |
2918 } | 2919 } |
2919 | 2920 |
2920 | 2921 |
2921 LocationSummary* UnaryMintOpInstr::MakeLocationSummary() const { | 2922 LocationSummary* UnaryMintOpInstr::MakeLocationSummary() const { |
2922 const intptr_t kNumInputs = 1; | 2923 const intptr_t kNumInputs = 1; |
2923 const intptr_t kNumTemps = 0; | 2924 const intptr_t kNumTemps = 0; |
2924 LocationSummary* summary = | 2925 LocationSummary* summary = |
2925 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2926 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
2926 summary->set_in(0, Location::RequiresXmmRegister()); | 2927 summary->set_in(0, Location::RequiresFpuRegister()); |
2927 summary->set_out(Location::SameAsFirstInput()); | 2928 summary->set_out(Location::SameAsFirstInput()); |
2928 return summary; | 2929 return summary; |
2929 } | 2930 } |
2930 | 2931 |
2931 | 2932 |
2932 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2933 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2933 ASSERT(op_kind() == Token::kBIT_NOT); | 2934 ASSERT(op_kind() == Token::kBIT_NOT); |
2934 XmmRegister value = locs()->in(0).xmm_reg(); | 2935 XmmRegister value = locs()->in(0).fpu_reg(); |
2935 ASSERT(value == locs()->out().xmm_reg()); | 2936 ASSERT(value == locs()->out().fpu_reg()); |
2936 __ pcmpeqq(XMM0, XMM0); // Generate all 1's. | 2937 __ pcmpeqq(XMM0, XMM0); // Generate all 1's. |
2937 __ pxor(value, XMM0); | 2938 __ pxor(value, XMM0); |
2938 } | 2939 } |
2939 | 2940 |
2940 | 2941 |
| 2942 LocationSummary* ThrowInstr::MakeLocationSummary() const { |
| 2943 return new LocationSummary(0, 0, LocationSummary::kCall); |
| 2944 } |
| 2945 |
| 2946 |
| 2947 |
| 2948 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2949 compiler->GenerateCallRuntime(token_pos(), |
| 2950 kThrowRuntimeEntry, |
| 2951 locs()); |
| 2952 __ int3(); |
| 2953 } |
| 2954 |
| 2955 |
| 2956 LocationSummary* ReThrowInstr::MakeLocationSummary() const { |
| 2957 return new LocationSummary(0, 0, LocationSummary::kCall); |
| 2958 } |
| 2959 |
| 2960 |
| 2961 void ReThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2962 compiler->GenerateCallRuntime(token_pos(), |
| 2963 kReThrowRuntimeEntry, |
| 2964 locs()); |
| 2965 __ int3(); |
| 2966 } |
| 2967 |
| 2968 |
| 2969 LocationSummary* GotoInstr::MakeLocationSummary() const { |
| 2970 return new LocationSummary(0, 0, LocationSummary::kNoCall); |
| 2971 } |
| 2972 |
| 2973 |
| 2974 void GotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2975 // Add deoptimization descriptor for deoptimizing instructions |
| 2976 // that may be inserted before this instruction. |
| 2977 if (!compiler->is_optimizing()) { |
| 2978 compiler->AddCurrentDescriptor(PcDescriptors::kDeoptBefore, |
| 2979 GetDeoptId(), |
| 2980 0); // No token position. |
| 2981 } |
| 2982 |
| 2983 if (HasParallelMove()) { |
| 2984 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); |
| 2985 } |
| 2986 |
| 2987 // We can fall through if the successor is the next block in the list. |
| 2988 // Otherwise, we need a jump. |
| 2989 if (!compiler->IsNextBlock(successor())) { |
| 2990 __ jmp(compiler->GetBlockLabel(successor())); |
| 2991 } |
| 2992 } |
| 2993 |
| 2994 |
| 2995 static Condition NegateCondition(Condition condition) { |
| 2996 switch (condition) { |
| 2997 case EQUAL: return NOT_EQUAL; |
| 2998 case NOT_EQUAL: return EQUAL; |
| 2999 case LESS: return GREATER_EQUAL; |
| 3000 case LESS_EQUAL: return GREATER; |
| 3001 case GREATER: return LESS_EQUAL; |
| 3002 case GREATER_EQUAL: return LESS; |
| 3003 case BELOW: return ABOVE_EQUAL; |
| 3004 case BELOW_EQUAL: return ABOVE; |
| 3005 case ABOVE: return BELOW_EQUAL; |
| 3006 case ABOVE_EQUAL: return BELOW; |
| 3007 default: |
| 3008 OS::Print("Error %d\n", condition); |
| 3009 UNIMPLEMENTED(); |
| 3010 return EQUAL; |
| 3011 } |
| 3012 } |
| 3013 |
| 3014 |
| 3015 void ControlInstruction::EmitBranchOnValue(FlowGraphCompiler* compiler, |
| 3016 bool value) { |
| 3017 if (value && compiler->IsNextBlock(false_successor())) { |
| 3018 __ jmp(compiler->GetBlockLabel(true_successor())); |
| 3019 } else if (!value && compiler->IsNextBlock(true_successor())) { |
| 3020 __ jmp(compiler->GetBlockLabel(false_successor())); |
| 3021 } |
| 3022 } |
| 3023 |
| 3024 |
| 3025 void ControlInstruction::EmitBranchOnCondition(FlowGraphCompiler* compiler, |
| 3026 Condition true_condition) { |
| 3027 if (compiler->IsNextBlock(false_successor())) { |
| 3028 // If the next block is the false successor we will fall through to it. |
| 3029 __ j(true_condition, compiler->GetBlockLabel(true_successor())); |
| 3030 } else { |
| 3031 // If the next block is the true successor we negate comparison and fall |
| 3032 // through to it. |
| 3033 ASSERT(compiler->IsNextBlock(true_successor())); |
| 3034 Condition false_condition = NegateCondition(true_condition); |
| 3035 __ j(false_condition, compiler->GetBlockLabel(false_successor())); |
| 3036 } |
| 3037 } |
| 3038 |
| 3039 |
| 3040 LocationSummary* CurrentContextInstr::MakeLocationSummary() const { |
| 3041 return LocationSummary::Make(0, |
| 3042 Location::RequiresRegister(), |
| 3043 LocationSummary::kNoCall); |
| 3044 } |
| 3045 |
| 3046 |
| 3047 void CurrentContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3048 __ MoveRegister(locs()->out().reg(), CTX); |
| 3049 } |
| 3050 |
| 3051 |
| 3052 LocationSummary* StrictCompareInstr::MakeLocationSummary() const { |
| 3053 const intptr_t kNumInputs = 2; |
| 3054 const intptr_t kNumTemps = 0; |
| 3055 LocationSummary* locs = |
| 3056 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3057 locs->set_in(0, Location::RegisterOrConstant(left())); |
| 3058 locs->set_in(1, Location::RegisterOrConstant(right())); |
| 3059 locs->set_out(Location::RequiresRegister()); |
| 3060 return locs; |
| 3061 } |
| 3062 |
| 3063 |
| 3064 // Special code for numbers (compare values instead of references.) |
| 3065 void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3066 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); |
| 3067 Location left = locs()->in(0); |
| 3068 Location right = locs()->in(1); |
| 3069 if (left.IsConstant() && right.IsConstant()) { |
| 3070 // TODO(vegorov): should be eliminated earlier by constant propagation. |
| 3071 const bool result = (kind() == Token::kEQ_STRICT) ? |
| 3072 left.constant().raw() == right.constant().raw() : |
| 3073 left.constant().raw() != right.constant().raw(); |
| 3074 __ LoadObject(locs()->out().reg(), result ? Bool::True() : Bool::False()); |
| 3075 return; |
| 3076 } |
| 3077 if (left.IsConstant()) { |
| 3078 compiler->EmitEqualityRegConstCompare(right.reg(), |
| 3079 left.constant(), |
| 3080 needs_number_check()); |
| 3081 } else if (right.IsConstant()) { |
| 3082 compiler->EmitEqualityRegConstCompare(left.reg(), |
| 3083 right.constant(), |
| 3084 needs_number_check()); |
| 3085 } else { |
| 3086 compiler->EmitEqualityRegRegCompare(left.reg(), |
| 3087 right.reg(), |
| 3088 needs_number_check()); |
| 3089 } |
| 3090 |
| 3091 Register result = locs()->out().reg(); |
| 3092 Label load_true, done; |
| 3093 Condition true_condition = (kind() == Token::kEQ_STRICT) ? EQUAL : NOT_EQUAL; |
| 3094 __ j(true_condition, &load_true, Assembler::kNearJump); |
| 3095 __ LoadObject(result, Bool::False()); |
| 3096 __ jmp(&done, Assembler::kNearJump); |
| 3097 __ Bind(&load_true); |
| 3098 __ LoadObject(result, Bool::True()); |
| 3099 __ Bind(&done); |
| 3100 } |
| 3101 |
| 3102 |
| 3103 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 3104 BranchInstr* branch) { |
| 3105 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); |
| 3106 Location left = locs()->in(0); |
| 3107 Location right = locs()->in(1); |
| 3108 if (left.IsConstant() && right.IsConstant()) { |
| 3109 // TODO(vegorov): should be eliminated earlier by constant propagation. |
| 3110 const bool result = (kind() == Token::kEQ_STRICT) ? |
| 3111 left.constant().raw() == right.constant().raw() : |
| 3112 left.constant().raw() != right.constant().raw(); |
| 3113 branch->EmitBranchOnValue(compiler, result); |
| 3114 return; |
| 3115 } |
| 3116 if (left.IsConstant()) { |
| 3117 compiler->EmitEqualityRegConstCompare(right.reg(), |
| 3118 left.constant(), |
| 3119 needs_number_check()); |
| 3120 } else if (right.IsConstant()) { |
| 3121 compiler->EmitEqualityRegConstCompare(left.reg(), |
| 3122 right.constant(), |
| 3123 needs_number_check()); |
| 3124 } else { |
| 3125 compiler->EmitEqualityRegRegCompare(left.reg(), |
| 3126 right.reg(), |
| 3127 needs_number_check()); |
| 3128 } |
| 3129 |
| 3130 Condition true_condition = (kind() == Token::kEQ_STRICT) ? EQUAL : NOT_EQUAL; |
| 3131 branch->EmitBranchOnCondition(compiler, true_condition); |
| 3132 } |
| 3133 |
| 3134 |
| 3135 void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3136 // The arguments to the stub include the closure, as does the arguments |
| 3137 // descriptor. |
| 3138 Register temp_reg = locs()->temp(0).reg(); |
| 3139 int argument_count = ArgumentCount(); |
| 3140 const Array& arguments_descriptor = |
| 3141 Array::ZoneHandle(ArgumentsDescriptor::New(argument_count, |
| 3142 argument_names())); |
| 3143 __ LoadObject(temp_reg, arguments_descriptor); |
| 3144 compiler->GenerateDartCall(deopt_id(), |
| 3145 token_pos(), |
| 3146 &StubCode::CallClosureFunctionLabel(), |
| 3147 PcDescriptors::kOther, |
| 3148 locs()); |
| 3149 __ Drop(argument_count); |
| 3150 } |
| 3151 |
| 3152 |
| 3153 LocationSummary* BooleanNegateInstr::MakeLocationSummary() const { |
| 3154 return LocationSummary::Make(1, |
| 3155 Location::RequiresRegister(), |
| 3156 LocationSummary::kNoCall); |
| 3157 } |
| 3158 |
| 3159 |
| 3160 void BooleanNegateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3161 Register value = locs()->in(0).reg(); |
| 3162 Register result = locs()->out().reg(); |
| 3163 |
| 3164 Label done; |
| 3165 __ LoadObject(result, Bool::True()); |
| 3166 __ CompareRegisters(result, value); |
| 3167 __ j(NOT_EQUAL, &done, Assembler::kNearJump); |
| 3168 __ LoadObject(result, Bool::False()); |
| 3169 __ Bind(&done); |
| 3170 } |
| 3171 |
| 3172 |
| 3173 LocationSummary* ChainContextInstr::MakeLocationSummary() const { |
| 3174 return LocationSummary::Make(1, |
| 3175 Location::NoLocation(), |
| 3176 LocationSummary::kNoCall); |
| 3177 } |
| 3178 |
| 3179 |
| 3180 void ChainContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3181 Register context_value = locs()->in(0).reg(); |
| 3182 |
| 3183 // Chain the new context in context_value to its parent in CTX. |
| 3184 __ StoreIntoObject(context_value, |
| 3185 FieldAddress(context_value, Context::parent_offset()), |
| 3186 CTX); |
| 3187 // Set new context as current context. |
| 3188 __ MoveRegister(CTX, context_value); |
| 3189 } |
| 3190 |
| 3191 |
| 3192 LocationSummary* StoreVMFieldInstr::MakeLocationSummary() const { |
| 3193 const intptr_t kNumInputs = 2; |
| 3194 const intptr_t kNumTemps = 0; |
| 3195 LocationSummary* locs = |
| 3196 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3197 locs->set_in(0, value()->NeedsStoreBuffer() ? Location::WritableRegister() |
| 3198 : Location::RequiresRegister()); |
| 3199 locs->set_in(1, Location::RequiresRegister()); |
| 3200 return locs; |
| 3201 } |
| 3202 |
| 3203 |
| 3204 void StoreVMFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3205 Register value_reg = locs()->in(0).reg(); |
| 3206 Register dest_reg = locs()->in(1).reg(); |
| 3207 |
| 3208 if (value()->NeedsStoreBuffer()) { |
| 3209 __ StoreIntoObject(dest_reg, FieldAddress(dest_reg, offset_in_bytes()), |
| 3210 value_reg); |
| 3211 } else { |
| 3212 __ StoreIntoObjectNoBarrier( |
| 3213 dest_reg, FieldAddress(dest_reg, offset_in_bytes()), value_reg); |
| 3214 } |
| 3215 } |
| 3216 |
| 3217 |
| 3218 LocationSummary* AllocateObjectInstr::MakeLocationSummary() const { |
| 3219 return MakeCallSummary(); |
| 3220 } |
| 3221 |
| 3222 |
| 3223 void AllocateObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3224 const Class& cls = Class::ZoneHandle(constructor().Owner()); |
| 3225 const Code& stub = Code::Handle(StubCode::GetAllocationStubForClass(cls)); |
| 3226 const ExternalLabel label(cls.ToCString(), stub.EntryPoint()); |
| 3227 compiler->GenerateCall(token_pos(), |
| 3228 &label, |
| 3229 PcDescriptors::kOther, |
| 3230 locs()); |
| 3231 __ Drop(ArgumentCount()); // Discard arguments. |
| 3232 } |
| 3233 |
| 3234 |
| 3235 LocationSummary* CreateClosureInstr::MakeLocationSummary() const { |
| 3236 return MakeCallSummary(); |
| 3237 } |
| 3238 |
| 3239 |
| 3240 void CreateClosureInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3241 const Function& closure_function = function(); |
| 3242 ASSERT(!closure_function.IsImplicitStaticClosureFunction()); |
| 3243 const Code& stub = Code::Handle( |
| 3244 StubCode::GetAllocationStubForClosure(closure_function)); |
| 3245 const ExternalLabel label(closure_function.ToCString(), stub.EntryPoint()); |
| 3246 compiler->GenerateCall(token_pos(), |
| 3247 &label, |
| 3248 PcDescriptors::kOther, |
| 3249 locs()); |
| 3250 __ Drop(2); // Discard type arguments and receiver. |
| 3251 } |
| 3252 |
2941 } // namespace dart | 3253 } // namespace dart |
2942 | 3254 |
2943 #undef __ | 3255 #undef __ |
2944 | 3256 |
2945 #endif // defined TARGET_ARCH_X64 | 3257 #endif // defined TARGET_ARCH_IA32 |
OLD | NEW |