Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013, 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_X64. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64. |
| 6 #if defined(TARGET_ARCH_X64) | 6 #if defined(TARGET_ARCH_X64) |
| 7 | 7 |
| 8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
| 9 | 9 |
| 10 #include "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
| (...skipping 355 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 366 default: | 366 default: |
| 367 UNREACHABLE(); | 367 UNREACHABLE(); |
| 368 return OVERFLOW; | 368 return OVERFLOW; |
| 369 } | 369 } |
| 370 } | 370 } |
| 371 | 371 |
| 372 | 372 |
| 373 LocationSummary* EqualityCompareInstr::MakeLocationSummary(Isolate* isolate, | 373 LocationSummary* EqualityCompareInstr::MakeLocationSummary(Isolate* isolate, |
| 374 bool opt) const { | 374 bool opt) const { |
| 375 const intptr_t kNumInputs = 2; | 375 const intptr_t kNumInputs = 2; |
| 376 if (operation_cid() == kMintCid) { | |
| 377 const intptr_t kNumTemps = 0; | |
| 378 LocationSummary* locs = new(isolate) LocationSummary( | |
| 379 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | |
| 380 locs->set_in(0, Location::RequiresRegister()); | |
| 381 locs->set_in(1, Location::RequiresRegister()); | |
| 382 locs->set_out(0, Location::RequiresRegister()); | |
| 383 return locs; | |
| 384 } | |
| 376 if (operation_cid() == kDoubleCid) { | 385 if (operation_cid() == kDoubleCid) { |
| 377 const intptr_t kNumTemps = 0; | 386 const intptr_t kNumTemps = 0; |
| 378 LocationSummary* locs = new(isolate) LocationSummary( | 387 LocationSummary* locs = new(isolate) LocationSummary( |
| 379 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 388 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 380 locs->set_in(0, Location::RequiresFpuRegister()); | 389 locs->set_in(0, Location::RequiresFpuRegister()); |
| 381 locs->set_in(1, Location::RequiresFpuRegister()); | 390 locs->set_in(1, Location::RequiresFpuRegister()); |
| 382 locs->set_out(0, Location::RequiresRegister()); | 391 locs->set_out(0, Location::RequiresRegister()); |
| 383 return locs; | 392 return locs; |
| 384 } | 393 } |
| 385 if (operation_cid() == kSmiCid) { | 394 if (operation_cid() == kSmiCid) { |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 475 __ CompareObject(left.reg(), right.constant(), PP); | 484 __ CompareObject(left.reg(), right.constant(), PP); |
| 476 } else if (right.IsStackSlot()) { | 485 } else if (right.IsStackSlot()) { |
| 477 __ cmpq(left.reg(), right.ToStackSlotAddress()); | 486 __ cmpq(left.reg(), right.ToStackSlotAddress()); |
| 478 } else { | 487 } else { |
| 479 __ cmpq(left.reg(), right.reg()); | 488 __ cmpq(left.reg(), right.reg()); |
| 480 } | 489 } |
| 481 return true_condition; | 490 return true_condition; |
| 482 } | 491 } |
| 483 | 492 |
| 484 | 493 |
| 494 static Condition TokenKindToMintCondition(Token::Kind kind) { | |
|
Vyacheslav Egorov (Google)
2014/10/05 18:46:59
I don't think there is a need to have this duplica
Cutch
2014/10/06 23:55:25
Done.
| |
| 495 switch (kind) { | |
| 496 case Token::kEQ: return EQUAL; | |
| 497 case Token::kNE: return NOT_EQUAL; | |
| 498 case Token::kLT: return LESS; | |
| 499 case Token::kGT: return GREATER; | |
| 500 case Token::kLTE: return LESS_EQUAL; | |
| 501 case Token::kGTE: return GREATER_EQUAL; | |
| 502 default: | |
| 503 UNREACHABLE(); | |
| 504 return OVERFLOW; | |
| 505 } | |
| 506 } | |
| 507 | |
| 508 | |
| 509 static Condition EmitMintComparisonOp(FlowGraphCompiler* compiler, | |
|
Vyacheslav Egorov (Google)
2014/10/05 18:47:00
This is essentially the same as EmitSmiComparisonO
Cutch
2014/10/06 23:55:25
Done.
| |
| 510 const LocationSummary& locs, | |
| 511 Token::Kind kind, | |
| 512 BranchLabels labels) { | |
| 513 const Location left = locs.in(0); | |
| 514 const Location right = locs.in(1); | |
| 515 | |
| 516 ASSERT(!left.IsConstant() || !right.IsConstant()); | |
| 517 | |
| 518 Condition true_condition = TokenKindToMintCondition(kind); | |
| 519 | |
| 520 __ cmpq(left.reg(), right.reg()); | |
| 521 | |
| 522 return true_condition; | |
| 523 } | |
| 524 | |
| 485 static Condition TokenKindToDoubleCondition(Token::Kind kind) { | 525 static Condition TokenKindToDoubleCondition(Token::Kind kind) { |
| 486 switch (kind) { | 526 switch (kind) { |
| 487 case Token::kEQ: return EQUAL; | 527 case Token::kEQ: return EQUAL; |
| 488 case Token::kNE: return NOT_EQUAL; | 528 case Token::kNE: return NOT_EQUAL; |
| 489 case Token::kLT: return BELOW; | 529 case Token::kLT: return BELOW; |
| 490 case Token::kGT: return ABOVE; | 530 case Token::kGT: return ABOVE; |
| 491 case Token::kLTE: return BELOW_EQUAL; | 531 case Token::kLTE: return BELOW_EQUAL; |
| 492 case Token::kGTE: return ABOVE_EQUAL; | 532 case Token::kGTE: return ABOVE_EQUAL; |
| 493 default: | 533 default: |
| 494 UNREACHABLE(); | 534 UNREACHABLE(); |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 511 ? labels.true_label : labels.false_label; | 551 ? labels.true_label : labels.false_label; |
| 512 __ j(PARITY_EVEN, nan_result); | 552 __ j(PARITY_EVEN, nan_result); |
| 513 return true_condition; | 553 return true_condition; |
| 514 } | 554 } |
| 515 | 555 |
| 516 | 556 |
| 517 Condition EqualityCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 557 Condition EqualityCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| 518 BranchLabels labels) { | 558 BranchLabels labels) { |
| 519 if (operation_cid() == kSmiCid) { | 559 if (operation_cid() == kSmiCid) { |
| 520 return EmitSmiComparisonOp(compiler, *locs(), kind(), labels); | 560 return EmitSmiComparisonOp(compiler, *locs(), kind(), labels); |
| 561 } else if (operation_cid() == kMintCid) { | |
| 562 return EmitMintComparisonOp(compiler, *locs(), kind(), labels); | |
| 521 } else { | 563 } else { |
| 522 ASSERT(operation_cid() == kDoubleCid); | 564 ASSERT(operation_cid() == kDoubleCid); |
| 523 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); | 565 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); |
| 524 } | 566 } |
| 525 } | 567 } |
| 526 | 568 |
| 527 | 569 |
| 528 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 570 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 529 ASSERT((kind() == Token::kEQ) || (kind() == Token::kNE)); | 571 ASSERT((kind() == Token::kEQ) || (kind() == Token::kNE)); |
| 530 | 572 |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 676 bool opt) const { | 718 bool opt) const { |
| 677 const intptr_t kNumInputs = 2; | 719 const intptr_t kNumInputs = 2; |
| 678 const intptr_t kNumTemps = 0; | 720 const intptr_t kNumTemps = 0; |
| 679 if (operation_cid() == kDoubleCid) { | 721 if (operation_cid() == kDoubleCid) { |
| 680 LocationSummary* summary = new(isolate) LocationSummary( | 722 LocationSummary* summary = new(isolate) LocationSummary( |
| 681 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 723 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 682 summary->set_in(0, Location::RequiresFpuRegister()); | 724 summary->set_in(0, Location::RequiresFpuRegister()); |
| 683 summary->set_in(1, Location::RequiresFpuRegister()); | 725 summary->set_in(1, Location::RequiresFpuRegister()); |
| 684 summary->set_out(0, Location::RequiresRegister()); | 726 summary->set_out(0, Location::RequiresRegister()); |
| 685 return summary; | 727 return summary; |
| 728 } else if (operation_cid() == kMintCid) { | |
| 729 LocationSummary* summary = new(isolate) LocationSummary( | |
| 730 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | |
| 731 summary->set_in(0, Location::RequiresRegister()); | |
| 732 summary->set_in(1, Location::RequiresRegister()); | |
| 733 summary->set_out(0, Location::RequiresRegister()); | |
| 734 return summary; | |
| 686 } | 735 } |
| 687 ASSERT(operation_cid() == kSmiCid); | 736 ASSERT(operation_cid() == kSmiCid); |
| 688 LocationSummary* summary = new(isolate) LocationSummary( | 737 LocationSummary* summary = new(isolate) LocationSummary( |
| 689 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 738 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 690 summary->set_in(0, Location::RegisterOrConstant(left())); | 739 summary->set_in(0, Location::RegisterOrConstant(left())); |
| 691 // Only one input can be a constant operand. The case of two constant | 740 // Only one input can be a constant operand. The case of two constant |
| 692 // operands should be handled by constant propagation. | 741 // operands should be handled by constant propagation. |
| 693 summary->set_in(1, summary->in(0).IsConstant() | 742 summary->set_in(1, summary->in(0).IsConstant() |
| 694 ? Location::RequiresRegister() | 743 ? Location::RequiresRegister() |
| 695 : Location::RegisterOrConstant(right())); | 744 : Location::RegisterOrConstant(right())); |
| 696 summary->set_out(0, Location::RequiresRegister()); | 745 summary->set_out(0, Location::RequiresRegister()); |
| 697 return summary; | 746 return summary; |
| 698 } | 747 } |
| 699 | 748 |
| 700 | 749 |
| 701 Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 750 Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| 702 BranchLabels labels) { | 751 BranchLabels labels) { |
| 703 if (operation_cid() == kSmiCid) { | 752 if (operation_cid() == kSmiCid) { |
| 704 return EmitSmiComparisonOp(compiler, *locs(), kind(), labels); | 753 return EmitSmiComparisonOp(compiler, *locs(), kind(), labels); |
| 754 } else if (operation_cid() == kMintCid) { | |
| 755 return EmitMintComparisonOp(compiler, *locs(), kind(), labels); | |
| 705 } else { | 756 } else { |
| 706 ASSERT(operation_cid() == kDoubleCid); | 757 ASSERT(operation_cid() == kDoubleCid); |
| 707 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); | 758 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); |
| 708 } | 759 } |
| 709 } | 760 } |
| 710 | 761 |
| 711 | 762 |
| 712 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 763 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 713 Label is_true, is_false; | 764 Label is_true, is_false; |
| 714 BranchLabels labels = { &is_true, &is_false, &is_false }; | 765 BranchLabels labels = { &is_true, &is_false, &is_false }; |
| (...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 941 case kExternalTypedDataUint8ArrayCid: | 992 case kExternalTypedDataUint8ArrayCid: |
| 942 case kExternalTypedDataUint8ClampedArrayCid: | 993 case kExternalTypedDataUint8ClampedArrayCid: |
| 943 case kTypedDataInt16ArrayCid: | 994 case kTypedDataInt16ArrayCid: |
| 944 case kTypedDataUint16ArrayCid: | 995 case kTypedDataUint16ArrayCid: |
| 945 case kOneByteStringCid: | 996 case kOneByteStringCid: |
| 946 case kTwoByteStringCid: | 997 case kTwoByteStringCid: |
| 947 case kTypedDataInt32ArrayCid: | 998 case kTypedDataInt32ArrayCid: |
| 948 case kTypedDataUint32ArrayCid: | 999 case kTypedDataUint32ArrayCid: |
| 949 return CompileType::FromCid(kSmiCid); | 1000 return CompileType::FromCid(kSmiCid); |
| 950 | 1001 |
| 1002 case kTypedDataInt64ArrayCid: | |
| 1003 return CompileType::Int(); | |
| 1004 | |
| 951 default: | 1005 default: |
| 952 UNIMPLEMENTED(); | 1006 UNIMPLEMENTED(); |
| 953 return CompileType::Dynamic(); | 1007 return CompileType::Dynamic(); |
| 954 } | 1008 } |
| 955 } | 1009 } |
| 956 | 1010 |
| 957 | 1011 |
| 958 Representation LoadIndexedInstr::representation() const { | 1012 Representation LoadIndexedInstr::representation() const { |
| 959 switch (class_id_) { | 1013 switch (class_id_) { |
| 960 case kArrayCid: | 1014 case kArrayCid: |
| 961 case kImmutableArrayCid: | 1015 case kImmutableArrayCid: |
| 962 case kTypedDataInt8ArrayCid: | 1016 case kTypedDataInt8ArrayCid: |
| 963 case kTypedDataUint8ArrayCid: | 1017 case kTypedDataUint8ArrayCid: |
| 964 case kTypedDataUint8ClampedArrayCid: | 1018 case kTypedDataUint8ClampedArrayCid: |
| 965 case kExternalTypedDataUint8ArrayCid: | 1019 case kExternalTypedDataUint8ArrayCid: |
| 966 case kExternalTypedDataUint8ClampedArrayCid: | 1020 case kExternalTypedDataUint8ClampedArrayCid: |
| 967 case kTypedDataInt16ArrayCid: | 1021 case kTypedDataInt16ArrayCid: |
| 968 case kTypedDataUint16ArrayCid: | 1022 case kTypedDataUint16ArrayCid: |
| 969 case kOneByteStringCid: | 1023 case kOneByteStringCid: |
| 970 case kTwoByteStringCid: | 1024 case kTwoByteStringCid: |
| 971 case kTypedDataInt32ArrayCid: | 1025 case kTypedDataInt32ArrayCid: |
| 972 case kTypedDataUint32ArrayCid: | 1026 case kTypedDataUint32ArrayCid: |
| 973 return kTagged; | 1027 return kTagged; |
| 1028 case kTypedDataInt64ArrayCid: | |
| 1029 return kUnboxedMint; | |
| 974 case kTypedDataFloat32ArrayCid: | 1030 case kTypedDataFloat32ArrayCid: |
| 975 case kTypedDataFloat64ArrayCid: | 1031 case kTypedDataFloat64ArrayCid: |
| 976 return kUnboxedDouble; | 1032 return kUnboxedDouble; |
| 977 case kTypedDataInt32x4ArrayCid: | 1033 case kTypedDataInt32x4ArrayCid: |
| 978 return kUnboxedInt32x4; | 1034 return kUnboxedInt32x4; |
| 979 case kTypedDataFloat32x4ArrayCid: | 1035 case kTypedDataFloat32x4ArrayCid: |
| 980 return kUnboxedFloat32x4; | 1036 return kUnboxedFloat32x4; |
| 981 case kTypedDataFloat64x2ArrayCid: | 1037 case kTypedDataFloat64x2ArrayCid: |
| 982 return kUnboxedFloat64x2; | 1038 return kUnboxedFloat64x2; |
| 983 default: | 1039 default: |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1079 __ SmiTag(result); | 1135 __ SmiTag(result); |
| 1080 break; | 1136 break; |
| 1081 case kTypedDataInt32ArrayCid: | 1137 case kTypedDataInt32ArrayCid: |
| 1082 __ movsxd(result, element_address); | 1138 __ movsxd(result, element_address); |
| 1083 __ SmiTag(result); | 1139 __ SmiTag(result); |
| 1084 break; | 1140 break; |
| 1085 case kTypedDataUint32ArrayCid: | 1141 case kTypedDataUint32ArrayCid: |
| 1086 __ movl(result, element_address); | 1142 __ movl(result, element_address); |
| 1087 __ SmiTag(result); | 1143 __ SmiTag(result); |
| 1088 break; | 1144 break; |
| 1145 case kTypedDataInt64ArrayCid: | |
| 1146 __ movq(result, element_address); | |
| 1147 break; | |
| 1089 default: | 1148 default: |
| 1090 ASSERT((class_id() == kArrayCid) || (class_id() == kImmutableArrayCid)); | 1149 ASSERT((class_id() == kArrayCid) || (class_id() == kImmutableArrayCid)); |
| 1091 __ movq(result, element_address); | 1150 __ movq(result, element_address); |
| 1092 break; | 1151 break; |
| 1093 } | 1152 } |
| 1094 } | 1153 } |
| 1095 | 1154 |
| 1096 | 1155 |
| 1097 Representation StoreIndexedInstr::RequiredInputRepresentation( | 1156 Representation StoreIndexedInstr::RequiredInputRepresentation( |
| 1098 intptr_t idx) const { | 1157 intptr_t idx) const { |
| 1099 if (idx == 0) return kNoRepresentation; | 1158 if (idx == 0) return kNoRepresentation; |
| 1100 if (idx == 1) return kTagged; | 1159 if (idx == 1) return kTagged; |
| 1101 ASSERT(idx == 2); | 1160 ASSERT(idx == 2); |
| 1102 switch (class_id_) { | 1161 switch (class_id_) { |
| 1103 case kArrayCid: | 1162 case kArrayCid: |
| 1104 case kOneByteStringCid: | 1163 case kOneByteStringCid: |
| 1105 case kTypedDataInt8ArrayCid: | 1164 case kTypedDataInt8ArrayCid: |
| 1106 case kTypedDataUint8ArrayCid: | 1165 case kTypedDataUint8ArrayCid: |
| 1107 case kExternalTypedDataUint8ArrayCid: | 1166 case kExternalTypedDataUint8ArrayCid: |
| 1108 case kTypedDataUint8ClampedArrayCid: | 1167 case kTypedDataUint8ClampedArrayCid: |
| 1109 case kExternalTypedDataUint8ClampedArrayCid: | 1168 case kExternalTypedDataUint8ClampedArrayCid: |
| 1110 case kTypedDataInt16ArrayCid: | 1169 case kTypedDataInt16ArrayCid: |
| 1111 case kTypedDataUint16ArrayCid: | 1170 case kTypedDataUint16ArrayCid: |
| 1112 return kTagged; | 1171 return kTagged; |
| 1113 case kTypedDataInt32ArrayCid: | 1172 case kTypedDataInt32ArrayCid: |
| 1114 return kUnboxedInt32; | 1173 return kUnboxedInt32; |
| 1115 case kTypedDataUint32ArrayCid: | 1174 case kTypedDataUint32ArrayCid: |
| 1116 return kUnboxedUint32; | 1175 return kUnboxedUint32; |
| 1176 case kTypedDataInt64ArrayCid: | |
| 1177 return kUnboxedMint; | |
| 1117 case kTypedDataFloat32ArrayCid: | 1178 case kTypedDataFloat32ArrayCid: |
| 1118 case kTypedDataFloat64ArrayCid: | 1179 case kTypedDataFloat64ArrayCid: |
| 1119 return kUnboxedDouble; | 1180 return kUnboxedDouble; |
| 1120 case kTypedDataFloat32x4ArrayCid: | 1181 case kTypedDataFloat32x4ArrayCid: |
| 1121 return kUnboxedFloat32x4; | 1182 return kUnboxedFloat32x4; |
| 1122 case kTypedDataInt32x4ArrayCid: | 1183 case kTypedDataInt32x4ArrayCid: |
| 1123 return kUnboxedInt32x4; | 1184 return kUnboxedInt32x4; |
| 1124 case kTypedDataFloat64x2ArrayCid: | 1185 case kTypedDataFloat64x2ArrayCid: |
| 1125 return kUnboxedFloat64x2; | 1186 return kUnboxedFloat64x2; |
| 1126 default: | 1187 default: |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1164 // RBX, RCX, RDX) instead of using a fixed register. | 1225 // RBX, RCX, RDX) instead of using a fixed register. |
| 1165 locs->set_in(2, Location::FixedRegisterOrSmiConstant(value(), RAX)); | 1226 locs->set_in(2, Location::FixedRegisterOrSmiConstant(value(), RAX)); |
| 1166 break; | 1227 break; |
| 1167 case kTypedDataInt16ArrayCid: | 1228 case kTypedDataInt16ArrayCid: |
| 1168 case kTypedDataUint16ArrayCid: | 1229 case kTypedDataUint16ArrayCid: |
| 1169 case kTypedDataInt32ArrayCid: | 1230 case kTypedDataInt32ArrayCid: |
| 1170 case kTypedDataUint32ArrayCid: | 1231 case kTypedDataUint32ArrayCid: |
| 1171 // Writable register because the value must be untagged before storing. | 1232 // Writable register because the value must be untagged before storing. |
| 1172 locs->set_in(2, Location::WritableRegister()); | 1233 locs->set_in(2, Location::WritableRegister()); |
| 1173 break; | 1234 break; |
| 1235 case kTypedDataInt64ArrayCid: | |
| 1236 locs->set_in(2, Location::RequiresRegister()); | |
| 1237 break; | |
| 1174 case kTypedDataFloat32ArrayCid: | 1238 case kTypedDataFloat32ArrayCid: |
| 1175 case kTypedDataFloat64ArrayCid: | 1239 case kTypedDataFloat64ArrayCid: |
| 1176 // TODO(srdjan): Support Float64 constants. | 1240 // TODO(srdjan): Support Float64 constants. |
| 1177 locs->set_in(2, Location::RequiresFpuRegister()); | 1241 locs->set_in(2, Location::RequiresFpuRegister()); |
| 1178 break; | 1242 break; |
| 1179 case kTypedDataInt32x4ArrayCid: | 1243 case kTypedDataInt32x4ArrayCid: |
| 1180 case kTypedDataFloat64x2ArrayCid: | 1244 case kTypedDataFloat64x2ArrayCid: |
| 1181 case kTypedDataFloat32x4ArrayCid: | 1245 case kTypedDataFloat32x4ArrayCid: |
| 1182 locs->set_in(2, Location::RequiresFpuRegister()); | 1246 locs->set_in(2, Location::RequiresFpuRegister()); |
| 1183 break; | 1247 break; |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1265 case kTypedDataUint16ArrayCid: { | 1329 case kTypedDataUint16ArrayCid: { |
| 1266 Register value = locs()->in(2).reg(); | 1330 Register value = locs()->in(2).reg(); |
| 1267 __ SmiUntag(value); | 1331 __ SmiUntag(value); |
| 1268 __ movw(element_address, value); | 1332 __ movw(element_address, value); |
| 1269 break; | 1333 break; |
| 1270 } | 1334 } |
| 1271 case kTypedDataInt32ArrayCid: | 1335 case kTypedDataInt32ArrayCid: |
| 1272 case kTypedDataUint32ArrayCid: { | 1336 case kTypedDataUint32ArrayCid: { |
| 1273 Register value = locs()->in(2).reg(); | 1337 Register value = locs()->in(2).reg(); |
| 1274 __ movl(element_address, value); | 1338 __ movl(element_address, value); |
| 1275 break; | 1339 break; |
| 1340 } | |
| 1341 case kTypedDataInt64ArrayCid: { | |
| 1342 Register value = locs()->in(2).reg(); | |
| 1343 __ movq(element_address, value); | |
| 1344 break; | |
| 1276 } | 1345 } |
| 1277 case kTypedDataFloat32ArrayCid: | 1346 case kTypedDataFloat32ArrayCid: |
| 1278 __ movss(element_address, locs()->in(2).fpu_reg()); | 1347 __ movss(element_address, locs()->in(2).fpu_reg()); |
| 1279 break; | 1348 break; |
| 1280 case kTypedDataFloat64ArrayCid: | 1349 case kTypedDataFloat64ArrayCid: |
| 1281 __ movsd(element_address, locs()->in(2).fpu_reg()); | 1350 __ movsd(element_address, locs()->in(2).fpu_reg()); |
| 1282 break; | 1351 break; |
| 1283 case kTypedDataInt32x4ArrayCid: | 1352 case kTypedDataInt32x4ArrayCid: |
| 1284 case kTypedDataFloat64x2ArrayCid: | 1353 case kTypedDataFloat64x2ArrayCid: |
| 1285 case kTypedDataFloat32x4ArrayCid: | 1354 case kTypedDataFloat32x4ArrayCid: |
| (...skipping 4147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5433 Register length = length_loc.reg(); | 5502 Register length = length_loc.reg(); |
| 5434 Register index = index_loc.reg(); | 5503 Register index = index_loc.reg(); |
| 5435 __ cmpq(index, length); | 5504 __ cmpq(index, length); |
| 5436 __ j(ABOVE_EQUAL, deopt); | 5505 __ j(ABOVE_EQUAL, deopt); |
| 5437 } | 5506 } |
| 5438 } | 5507 } |
| 5439 | 5508 |
| 5440 | 5509 |
| 5441 LocationSummary* UnboxIntegerInstr::MakeLocationSummary(Isolate* isolate, | 5510 LocationSummary* UnboxIntegerInstr::MakeLocationSummary(Isolate* isolate, |
| 5442 bool opt) const { | 5511 bool opt) const { |
| 5443 UNIMPLEMENTED(); | 5512 const intptr_t kNumInputs = 1; |
| 5444 return NULL; | 5513 const intptr_t kNumTemps = 0; |
| 5514 LocationSummary* locs = new(isolate) LocationSummary( | |
| 5515 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | |
| 5516 locs->set_in(0, Location::RequiresRegister()); | |
| 5517 locs->set_out(0, Location::RequiresRegister()); | |
| 5518 return locs; | |
| 5445 } | 5519 } |
| 5446 | 5520 |
| 5447 | 5521 |
| 5448 void UnboxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5522 void UnboxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5449 UNIMPLEMENTED(); | 5523 const intptr_t value_cid = value()->Type()->ToCid(); |
| 5524 const Register value = locs()->in(0).reg(); | |
| 5525 const Register result = locs()->out(0).reg(); | |
| 5526 | |
| 5527 if (value_cid == kMintCid) { | |
| 5528 __ movq(result, FieldAddress(value, Mint::value_offset())); | |
| 5529 } else if (value_cid == kSmiCid) { | |
| 5530 __ movq(result, value); | |
| 5531 __ SmiUntag(result); | |
| 5532 } else { | |
| 5533 Label* deopt = compiler->AddDeoptStub(deopt_id_, | |
| 5534 ICData::kDeoptUnboxInteger); | |
| 5535 Label is_smi, done; | |
| 5536 __ testq(value, Immediate(kSmiTagMask)); | |
|
Vyacheslav Egorov (Google)
2014/10/05 18:46:59
You can produce much smaller instruction sequence
Cutch
2014/10/06 23:55:26
Done.
| |
| 5537 __ j(ZERO, &is_smi); | |
| 5538 __ CompareClassId(value, kMintCid); | |
| 5539 __ j(NOT_EQUAL, deopt); | |
| 5540 __ movq(result, FieldAddress(value, Mint::value_offset())); | |
| 5541 __ jmp(&done); | |
| 5542 __ Bind(&is_smi); | |
| 5543 __ movq(result, value); | |
| 5544 __ SmiUntag(result); | |
| 5545 __ Bind(&done); | |
| 5546 } | |
| 5450 } | 5547 } |
| 5451 | 5548 |
| 5452 | 5549 |
| 5453 LocationSummary* BoxIntegerInstr::MakeLocationSummary(Isolate* isolate, | 5550 LocationSummary* BoxIntegerInstr::MakeLocationSummary(Isolate* isolate, |
| 5454 bool opt) const { | 5551 bool opt) const { |
| 5455 UNIMPLEMENTED(); | 5552 const intptr_t kNumInputs = 1; |
| 5456 return NULL; | 5553 const intptr_t kNumTemps = 0; |
| 5554 LocationSummary* summary = new(isolate) LocationSummary( | |
| 5555 isolate, kNumInputs, kNumTemps, is_smi() | |
| 5556 ? LocationSummary::kNoCall | |
| 5557 : LocationSummary::kCallOnSlowPath); | |
| 5558 summary->set_in(0, Location::RequiresRegister()); | |
| 5559 summary->set_out(0, Location::RequiresRegister()); | |
| 5560 return summary; | |
| 5457 } | 5561 } |
| 5458 | 5562 |
| 5459 | 5563 |
| 5460 void BoxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5564 void BoxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5461 UNIMPLEMENTED(); | 5565 const Register out = locs()->out(0).reg(); |
| 5566 const Register value = locs()->in(0).reg(); | |
| 5567 | |
| 5568 if (is_smi()) { | |
| 5569 __ movq(out, value); | |
| 5570 __ SmiTag(out); | |
| 5571 return; | |
| 5572 } | |
| 5573 | |
| 5574 Label is_smi; | |
| 5575 Label done; | |
| 5576 // Tag, Untag, and then compare with original value. | |
| 5577 __ movq(out, value); | |
| 5578 __ SmiTag(out); | |
| 5579 __ SmiUntag(out); | |
|
Vyacheslav Egorov (Google)
2014/10/05 18:46:59
__ movq(out, value);
__ SmiTag(out); // shrl set
Cutch
2014/10/06 23:55:25
Done.
| |
| 5580 __ cmpq(out, value); | |
| 5581 __ j(EQUAL, &is_smi); | |
| 5582 BoxAllocationSlowPath::Allocate( | |
| 5583 compiler, this, compiler->mint_class(), out); | |
| 5584 __ movq(FieldAddress(out, Mint::value_offset()), value); | |
| 5585 __ jmp(&done); | |
| 5586 __ Bind(&is_smi); | |
| 5587 __ movq(out, value); | |
| 5588 __ SmiTag(out); | |
| 5589 __ Bind(&done); | |
| 5462 } | 5590 } |
| 5463 | 5591 |
| 5464 | 5592 |
| 5465 LocationSummary* BinaryMintOpInstr::MakeLocationSummary(Isolate* isolate, | 5593 LocationSummary* BinaryMintOpInstr::MakeLocationSummary(Isolate* isolate, |
| 5466 bool opt) const { | 5594 bool opt) const { |
| 5467 UNIMPLEMENTED(); | 5595 const intptr_t kNumInputs = 2; |
| 5468 return NULL; | 5596 const intptr_t kNumTemps = 0; |
| 5597 LocationSummary* summary = new(isolate) LocationSummary( | |
| 5598 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | |
| 5599 summary->set_in(0, Location::RequiresRegister()); | |
| 5600 summary->set_in(1, Location::RequiresRegister()); | |
| 5601 summary->set_out(0, Location::SameAsFirstInput()); | |
| 5602 return summary; | |
| 5469 } | 5603 } |
| 5470 | 5604 |
| 5471 | 5605 |
| 5472 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5606 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5473 UNIMPLEMENTED(); | 5607 const Register left = locs()->in(0).reg(); |
| 5608 const Register right = locs()->in(1).reg(); | |
| 5609 const Register out = locs()->out(0).reg(); | |
| 5610 | |
| 5611 ASSERT(out == left); | |
| 5612 | |
| 5613 Label* deopt = NULL; | |
| 5614 if (CanDeoptimize()) { | |
| 5615 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp); | |
| 5616 } | |
| 5617 | |
| 5618 switch (op_kind()) { | |
|
Vyacheslav Egorov (Google)
2014/10/05 18:46:59
use EmitIntegerArithmetic
Cutch
2014/10/06 23:55:25
EmitIntegerArithmetic does 32-bit operations, thes
Vyacheslav Egorov (Google)
2014/10/07 12:03:50
Ack, true, shame on me!
I was dwelling in ia32-t
Cutch
2014/10/21 17:42:11
Done.
| |
| 5619 case Token::kBIT_AND: | |
| 5620 __ andq(left, right); | |
| 5621 break; | |
| 5622 case Token::kBIT_OR: | |
| 5623 __ orq(left, right); | |
| 5624 break; | |
| 5625 case Token::kBIT_XOR: | |
| 5626 __ xorq(left, right); | |
| 5627 break; | |
| 5628 case Token::kADD: | |
| 5629 case Token::kSUB: { | |
| 5630 if (op_kind() == Token::kADD) { | |
| 5631 __ addq(left, right); | |
| 5632 } else { | |
| 5633 __ subq(left, right); | |
| 5634 } | |
| 5635 if (can_overflow()) { | |
| 5636 ASSERT(deopt != NULL); | |
| 5637 __ j(OVERFLOW, deopt); | |
| 5638 } | |
| 5639 break; | |
| 5640 } | |
| 5641 case Token::kMUL: | |
| 5642 __ imulq(left, right); | |
| 5643 ASSERT(deopt != NULL); | |
| 5644 __ j(OVERFLOW, deopt); | |
| 5645 break; | |
| 5646 default: | |
| 5647 UNREACHABLE(); | |
| 5648 break; | |
| 5649 } | |
| 5650 if (FLAG_throw_on_javascript_int_overflow) { | |
| 5651 EmitJavascriptOverflowCheck(compiler, range(), deopt, out); | |
| 5652 } | |
| 5474 } | 5653 } |
| 5475 | 5654 |
| 5476 | 5655 |
| 5477 LocationSummary* UnaryMintOpInstr::MakeLocationSummary(Isolate* isolate, | 5656 LocationSummary* UnaryMintOpInstr::MakeLocationSummary(Isolate* isolate, |
| 5478 bool opt) const { | 5657 bool opt) const { |
| 5479 UNIMPLEMENTED(); | 5658 const intptr_t kNumInputs = 1; |
| 5480 return NULL; | 5659 const intptr_t kNumTemps = 0; |
| 5660 LocationSummary* summary = new(isolate) LocationSummary( | |
| 5661 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | |
| 5662 summary->set_in(0, Location::RequiresRegister()); | |
| 5663 summary->set_out(0, Location::SameAsFirstInput()); | |
| 5664 return summary; | |
| 5481 } | 5665 } |
| 5482 | 5666 |
| 5483 | 5667 |
| 5484 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5668 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5485 UNIMPLEMENTED(); | 5669 ASSERT(op_kind() == Token::kBIT_NOT); |
| 5486 } | 5670 const Register left = locs()->in(0).reg(); |
| 5487 | 5671 const Register out = locs()->out(0).reg(); |
| 5672 ASSERT(out == left); | |
| 5673 | |
| 5674 Label* deopt = NULL; | |
| 5675 if (FLAG_throw_on_javascript_int_overflow) { | |
| 5676 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryMintOp); | |
| 5677 } | |
| 5678 | |
| 5679 __ notq(left); | |
| 5680 | |
| 5681 if (FLAG_throw_on_javascript_int_overflow) { | |
| 5682 EmitJavascriptOverflowCheck(compiler, range(), deopt, out); | |
| 5683 } | |
| 5684 } | |
| 5685 | |
| 5686 | |
| 5687 static const intptr_t kMintShiftCountLimit = 63; | |
| 5488 | 5688 |
| 5489 bool ShiftMintOpInstr::has_shift_count_check() const { | 5689 bool ShiftMintOpInstr::has_shift_count_check() const { |
| 5490 UNREACHABLE(); | 5690 return !RangeUtils::IsWithin( |
| 5491 return false; | 5691 right()->definition()->range(), 0, kMintShiftCountLimit); |
| 5492 } | 5692 } |
| 5493 | 5693 |
| 5494 | 5694 |
| 5495 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(Isolate* isolate, | 5695 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(Isolate* isolate, |
| 5496 bool opt) const { | 5696 bool opt) const { |
| 5497 UNIMPLEMENTED(); | 5697 const intptr_t kNumInputs = 2; |
| 5498 return NULL; | 5698 const intptr_t kNumTemps = can_overflow() ? 1 : 0; |
| 5699 LocationSummary* summary = new(isolate) LocationSummary( | |
| 5700 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | |
| 5701 summary->set_in(0, Location::RequiresRegister()); | |
| 5702 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), RCX)); | |
| 5703 if (kNumTemps > 0) { | |
| 5704 summary->set_temp(0, Location::RequiresRegister()); | |
| 5705 } | |
| 5706 summary->set_out(0, Location::SameAsFirstInput()); | |
| 5707 return summary; | |
| 5499 } | 5708 } |
| 5500 | 5709 |
| 5501 | 5710 |
| 5502 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5711 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5503 UNIMPLEMENTED(); | 5712 const Register left = locs()->in(0).reg(); |
| 5504 } | 5713 const Register out = locs()->out(0).reg(); |
| 5505 | 5714 ASSERT(left == out); |
| 5506 | 5715 |
| 5716 Label* deopt = NULL; | |
| 5717 if (CanDeoptimize()) { | |
| 5718 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptShiftMintOp); | |
| 5719 } | |
| 5720 if (locs()->in(1).IsConstant()) { | |
| 5721 // Code for a constant shift amount. | |
| 5722 ASSERT(locs()->in(1).constant().IsSmi()); | |
| 5723 const int64_t shift = | |
| 5724 reinterpret_cast<int64_t>(locs()->in(1).constant().raw()) >> 1; | |
| 5725 if ((shift < 0) || (shift > kMintShiftCountLimit)) { | |
|
Vyacheslav Egorov (Google)
2014/10/05 18:47:00
These cases should be handled in the Canonicalize
Cutch
2014/10/06 23:55:26
Done.
| |
| 5726 __ jmp(deopt); | |
| 5727 return; | |
| 5728 } else if (shift == 0) { | |
| 5729 // Nothing to do for zero shift amount. | |
| 5730 return; | |
| 5731 } | |
| 5732 switch (op_kind()) { | |
| 5733 case Token::kSHR: | |
| 5734 __ sarq(left, Immediate(shift)); | |
| 5735 break; | |
| 5736 case Token::kSHL: { | |
| 5737 if (can_overflow()) { | |
| 5738 // Check for overflow. | |
| 5739 Register temp = locs()->temp(0).reg(); | |
| 5740 __ movq(temp, left); | |
| 5741 __ shlq(left, Immediate(shift)); | |
| 5742 __ sarq(left, Immediate(shift)); | |
| 5743 __ cmpq(left, temp); | |
| 5744 __ j(NOT_EQUAL, deopt); // Overflow. | |
| 5745 } | |
| 5746 // Shift for result now we know there is no overflow. | |
| 5747 __ shlq(left, Immediate(shift)); | |
| 5748 break; | |
| 5749 } | |
| 5750 default: | |
| 5751 UNREACHABLE(); | |
| 5752 } | |
| 5753 } else { | |
| 5754 // Code for a variable shift amount. | |
| 5755 // Deoptimize if shift count is > 63. | |
| 5756 // sarl operation masks the count to 5 bits and | |
| 5757 // shrd is undefined with count > operand size (32) | |
| 5758 __ SmiUntag(RCX); | |
| 5759 if (has_shift_count_check()) { | |
| 5760 __ cmpq(RCX, Immediate(kMintShiftCountLimit)); | |
| 5761 __ j(ABOVE, deopt); | |
| 5762 } | |
| 5763 Label done, large_shift; | |
| 5764 switch (op_kind()) { | |
| 5765 case Token::kSHR: { | |
| 5766 __ sarq(left, RCX); | |
| 5767 break; | |
| 5768 } | |
| 5769 case Token::kSHL: { | |
| 5770 if (can_overflow()) { | |
| 5771 // Check for overflow. | |
| 5772 Register temp = locs()->temp(0).reg(); | |
| 5773 __ movq(temp, left); | |
| 5774 __ shlq(left, RCX); | |
| 5775 __ sarq(left, RCX); | |
| 5776 __ cmpq(left, temp); | |
| 5777 __ j(NOT_EQUAL, deopt); // Overflow. | |
| 5778 } | |
| 5779 // Shift for result now we know there is no overflow. | |
| 5780 __ shlq(left, RCX); | |
| 5781 break; | |
| 5782 } | |
| 5783 default: | |
| 5784 UNREACHABLE(); | |
| 5785 } | |
| 5786 } | |
| 5787 if (FLAG_throw_on_javascript_int_overflow) { | |
| 5788 EmitJavascriptOverflowCheck(compiler, range(), deopt, out); | |
| 5789 } | |
| 5790 } | |
| 5791 | |
| 5792 | |
| 5507 CompileType BinaryUint32OpInstr::ComputeType() const { | 5793 CompileType BinaryUint32OpInstr::ComputeType() const { |
| 5508 return CompileType::FromCid(kSmiCid); | 5794 return CompileType::FromCid(kSmiCid); |
| 5509 } | 5795 } |
| 5510 | 5796 |
| 5511 | 5797 |
| 5512 CompileType ShiftUint32OpInstr::ComputeType() const { | 5798 CompileType ShiftUint32OpInstr::ComputeType() const { |
| 5513 return CompileType::FromCid(kSmiCid); | 5799 return CompileType::FromCid(kSmiCid); |
| 5514 } | 5800 } |
| 5515 | 5801 |
| 5516 | 5802 |
| 5517 CompileType UnaryUint32OpInstr::ComputeType() const { | 5803 CompileType UnaryUint32OpInstr::ComputeType() const { |
| 5518 return CompileType::FromCid(kSmiCid); | 5804 return CompileType::FromCid(kSmiCid); |
| 5519 } | 5805 } |
| 5520 | 5806 |
| 5521 | 5807 |
| 5522 DEFINE_UNIMPLEMENTED_INSTRUCTION(BinaryUint32OpInstr) | 5808 LocationSummary* BinaryUint32OpInstr::MakeLocationSummary(Isolate* isolate, |
| 5523 DEFINE_UNIMPLEMENTED_INSTRUCTION(ShiftUint32OpInstr) | 5809 bool opt) const { |
| 5524 DEFINE_UNIMPLEMENTED_INSTRUCTION(UnaryUint32OpInstr) | 5810 const intptr_t kNumInputs = 2; |
| 5811 const intptr_t kNumTemps = (op_kind() == Token::kMUL) ? 1 : 0; | |
| 5812 LocationSummary* summary = new(isolate) LocationSummary( | |
| 5813 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | |
| 5814 summary->set_in(0, Location::RequiresRegister()); | |
| 5815 summary->set_in(1, Location::RequiresRegister()); | |
| 5816 summary->set_out(0, Location::SameAsFirstInput()); | |
| 5817 return summary; | |
| 5818 } | |
| 5819 | |
| 5820 | |
| 5821 template<typename OperandType> | |
| 5822 static void EmitIntegerArithmetic(FlowGraphCompiler* compiler, | |
| 5823 Token::Kind op_kind, | |
| 5824 Register left, | |
| 5825 const OperandType& right, | |
| 5826 Label* deopt) { | |
| 5827 switch (op_kind) { | |
| 5828 case Token::kADD: | |
| 5829 __ addl(left, right); | |
| 5830 break; | |
| 5831 case Token::kSUB: | |
| 5832 __ subl(left, right); | |
| 5833 break; | |
| 5834 case Token::kBIT_AND: | |
| 5835 __ andl(left, right); | |
| 5836 break; | |
| 5837 case Token::kBIT_OR: | |
| 5838 __ orl(left, right); | |
| 5839 break; | |
| 5840 case Token::kBIT_XOR: | |
| 5841 __ xorl(left, right); | |
| 5842 break; | |
| 5843 case Token::kMUL: | |
| 5844 __ imull(left, right); | |
| 5845 break; | |
| 5846 default: | |
| 5847 UNREACHABLE(); | |
| 5848 } | |
| 5849 if (deopt != NULL) __ j(OVERFLOW, deopt); | |
| 5850 } | |
| 5851 | |
| 5852 | |
| 5853 void BinaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 5854 Register left = locs()->in(0).reg(); | |
| 5855 Register right = locs()->in(1).reg(); | |
| 5856 Register out = locs()->out(0).reg(); | |
| 5857 ASSERT(out == left); | |
| 5858 switch (op_kind()) { | |
| 5859 case Token::kBIT_AND: | |
| 5860 case Token::kBIT_OR: | |
| 5861 case Token::kBIT_XOR: | |
| 5862 case Token::kADD: | |
| 5863 case Token::kSUB: | |
| 5864 case Token::kMUL: | |
| 5865 EmitIntegerArithmetic(compiler, op_kind(), left, right, NULL); | |
| 5866 return; | |
| 5867 default: | |
| 5868 UNREACHABLE(); | |
| 5869 } | |
| 5870 } | |
| 5871 | |
| 5872 | |
| 5873 LocationSummary* ShiftUint32OpInstr::MakeLocationSummary(Isolate* isolate, | |
| 5874 bool opt) const { | |
| 5875 const intptr_t kNumInputs = 2; | |
| 5876 const intptr_t kNumTemps = 0; | |
| 5877 LocationSummary* summary = new(isolate) LocationSummary( | |
| 5878 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | |
| 5879 summary->set_in(0, Location::RequiresRegister()); | |
| 5880 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), RCX)); | |
| 5881 summary->set_out(0, Location::SameAsFirstInput()); | |
| 5882 return summary; | |
| 5883 } | |
| 5884 | |
| 5885 | |
| 5886 void ShiftUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 5887 const intptr_t kShifterLimit = 31; | |
| 5888 | |
| 5889 Register left = locs()->in(0).reg(); | |
| 5890 Register out = locs()->out(0).reg(); | |
| 5891 ASSERT(left == out); | |
| 5892 | |
| 5893 | |
| 5894 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptShiftMintOp); | |
| 5895 | |
| 5896 if (locs()->in(1).IsConstant()) { | |
| 5897 // Shifter is constant. | |
| 5898 | |
| 5899 const Object& constant = locs()->in(1).constant(); | |
| 5900 ASSERT(constant.IsSmi()); | |
| 5901 const intptr_t shift_value = Smi::Cast(constant).Value(); | |
| 5902 | |
| 5903 // Check constant shift value. | |
| 5904 if (shift_value == 0) { | |
|
Vyacheslav Egorov (Google)
2014/10/05 18:46:59
Should be handled in the Canonicalize
Cutch
2014/10/06 23:55:25
Done.
| |
| 5905 // Nothing to do. | |
| 5906 } else if (shift_value < 0) { | |
| 5907 // Invalid shift value. | |
| 5908 __ jmp(deopt); | |
| 5909 } else if (shift_value > kShifterLimit) { | |
| 5910 // Result is 0. | |
| 5911 __ xorq(left, left); | |
| 5912 } else { | |
| 5913 // Do the shift: (shift_value > 0) && (shift_value <= kShifterLimit). | |
| 5914 switch (op_kind()) { | |
| 5915 case Token::kSHR: | |
| 5916 __ shrl(left, Immediate(shift_value)); | |
| 5917 break; | |
| 5918 case Token::kSHL: | |
| 5919 __ shll(left, Immediate(shift_value)); | |
| 5920 break; | |
| 5921 default: | |
| 5922 UNREACHABLE(); | |
| 5923 } | |
| 5924 } | |
| 5925 return; | |
| 5926 } | |
| 5927 | |
| 5928 // Non constant shift value. | |
| 5929 | |
| 5930 Register shifter = locs()->in(1).reg(); | |
| 5931 ASSERT(shifter == RCX); | |
| 5932 | |
| 5933 Label done; | |
| 5934 Label zero; | |
| 5935 | |
| 5936 // TODO(johnmccutchan): Use range information to avoid these checks. | |
| 5937 __ SmiUntag(shifter); | |
| 5938 __ cmpq(shifter, Immediate(0)); | |
| 5939 // If shift value is < 0, deoptimize. | |
| 5940 __ j(NEGATIVE, deopt); | |
| 5941 __ cmpq(shifter, Immediate(kShifterLimit)); | |
| 5942 // If shift value is >= 32, return zero. | |
| 5943 __ j(ABOVE, &zero); | |
| 5944 | |
| 5945 // Do the shift. | |
| 5946 switch (op_kind()) { | |
| 5947 case Token::kSHR: | |
| 5948 __ shrl(left, shifter); | |
| 5949 __ jmp(&done); | |
| 5950 break; | |
| 5951 case Token::kSHL: | |
| 5952 __ shll(left, shifter); | |
| 5953 __ jmp(&done); | |
| 5954 break; | |
| 5955 default: | |
| 5956 UNREACHABLE(); | |
| 5957 } | |
| 5958 | |
| 5959 __ Bind(&zero); | |
| 5960 // Shift was greater than 31 bits, just return zero. | |
| 5961 __ xorq(left, left); | |
| 5962 | |
| 5963 // Exit path. | |
| 5964 __ Bind(&done); | |
| 5965 } | |
| 5966 | |
| 5967 | |
| 5968 LocationSummary* UnaryUint32OpInstr::MakeLocationSummary(Isolate* isolate, | |
| 5969 bool opt) const { | |
| 5970 const intptr_t kNumInputs = 1; | |
| 5971 const intptr_t kNumTemps = 0; | |
| 5972 LocationSummary* summary = new(isolate) LocationSummary( | |
| 5973 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | |
| 5974 summary->set_in(0, Location::RequiresRegister()); | |
| 5975 summary->set_out(0, Location::SameAsFirstInput()); | |
| 5976 return summary; | |
| 5977 } | |
| 5978 | |
| 5979 | |
| 5980 void UnaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 5981 Register out = locs()->out(0).reg(); | |
| 5982 ASSERT(locs()->in(0).reg() == out); | |
| 5983 | |
| 5984 ASSERT(op_kind() == Token::kBIT_NOT); | |
| 5985 | |
| 5986 __ notl(out); | |
| 5987 } | |
| 5988 | |
| 5989 | |
| 5525 DEFINE_UNIMPLEMENTED_INSTRUCTION(BinaryInt32OpInstr) | 5990 DEFINE_UNIMPLEMENTED_INSTRUCTION(BinaryInt32OpInstr) |
| 5526 | 5991 |
| 5527 | 5992 |
| 5528 LocationSummary* UnboxIntNInstr::MakeLocationSummary(Isolate* isolate, | 5993 LocationSummary* UnboxIntNInstr::MakeLocationSummary(Isolate* isolate, |
| 5529 bool opt) const { | 5994 bool opt) const { |
| 5530 const intptr_t kNumInputs = 1; | 5995 const intptr_t kNumInputs = 1; |
| 5531 const intptr_t kNumTemps = (!is_truncating() && CanDeoptimize()) ? 1 : 0; | 5996 const intptr_t kNumTemps = (!is_truncating() && CanDeoptimize()) ? 1 : 0; |
| 5532 LocationSummary* summary = new(isolate) LocationSummary( | 5997 LocationSummary* summary = new(isolate) LocationSummary( |
| 5533 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5998 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5534 summary->set_in(0, Location::RequiresRegister()); | 5999 summary->set_in(0, Location::RequiresRegister()); |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5606 } | 6071 } |
| 5607 | 6072 |
| 5608 | 6073 |
| 5609 LocationSummary* UnboxedIntConverterInstr::MakeLocationSummary(Isolate* isolate, | 6074 LocationSummary* UnboxedIntConverterInstr::MakeLocationSummary(Isolate* isolate, |
| 5610 bool opt) const { | 6075 bool opt) const { |
| 5611 const intptr_t kNumInputs = 1; | 6076 const intptr_t kNumInputs = 1; |
| 5612 const intptr_t kNumTemps = 0; | 6077 const intptr_t kNumTemps = 0; |
| 5613 LocationSummary* summary = new(isolate) LocationSummary( | 6078 LocationSummary* summary = new(isolate) LocationSummary( |
| 5614 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6079 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5615 if (from() == kUnboxedMint) { | 6080 if (from() == kUnboxedMint) { |
| 5616 UNREACHABLE(); | 6081 ASSERT((to() == kUnboxedUint32) || (to() == kUnboxedInt32)); |
| 6082 summary->set_in(0, Location::RequiresRegister()); | |
| 6083 summary->set_out(0, Location::SameAsFirstInput()); | |
| 5617 } else if (to() == kUnboxedMint) { | 6084 } else if (to() == kUnboxedMint) { |
| 5618 UNREACHABLE(); | 6085 ASSERT((from() == kUnboxedInt32) || (from() == kUnboxedUint32)); |
| 6086 summary->set_in(0, Location::RequiresRegister()); | |
| 6087 summary->set_out(0, Location::SameAsFirstInput()); | |
| 5619 } else { | 6088 } else { |
| 5620 ASSERT((to() == kUnboxedUint32) || (to() == kUnboxedInt32)); | 6089 ASSERT((to() == kUnboxedUint32) || (to() == kUnboxedInt32)); |
| 5621 ASSERT((from() == kUnboxedUint32) || (from() == kUnboxedInt32)); | 6090 ASSERT((from() == kUnboxedUint32) || (from() == kUnboxedInt32)); |
| 5622 summary->set_in(0, Location::RequiresRegister()); | 6091 summary->set_in(0, Location::RequiresRegister()); |
| 5623 summary->set_out(0, Location::SameAsFirstInput()); | 6092 summary->set_out(0, Location::SameAsFirstInput()); |
| 5624 } | 6093 } |
| 5625 return summary; | 6094 return summary; |
| 5626 } | 6095 } |
| 5627 | 6096 |
| 5628 | 6097 |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 5640 const Register value = locs()->in(0).reg(); | 6109 const Register value = locs()->in(0).reg(); |
| 5641 const Register out = locs()->out(0).reg(); | 6110 const Register out = locs()->out(0).reg(); |
| 5642 __ movsxd(out, value); | 6111 __ movsxd(out, value); |
| 5643 if (CanDeoptimize()) { | 6112 if (CanDeoptimize()) { |
| 5644 Label* deopt = | 6113 Label* deopt = |
| 5645 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnboxInteger); | 6114 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnboxInteger); |
| 5646 __ testl(out, out); | 6115 __ testl(out, out); |
| 5647 __ j(NEGATIVE, deopt); | 6116 __ j(NEGATIVE, deopt); |
| 5648 } | 6117 } |
| 5649 } else if (from() == kUnboxedMint) { | 6118 } else if (from() == kUnboxedMint) { |
| 5650 UNREACHABLE(); | 6119 ASSERT((to() == kUnboxedUint32) || (to() == kUnboxedInt32)); |
| 6120 const Register value = locs()->in(0).reg(); | |
| 6121 const Register out = locs()->out(0).reg(); | |
| 6122 // Copy low. | |
| 6123 __ movl(out, value); | |
| 6124 if (CanDeoptimize()) { | |
| 6125 Label* deopt = | |
| 6126 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnboxInteger); | |
| 6127 // Sign extend. | |
| 6128 __ movsxd(out, out); | |
|
Vyacheslav Egorov (Google)
2014/10/05 18:47:00
you could do __ movsxd(out, value) to begin with.
Cutch
2014/10/06 23:55:26
Done.
| |
| 6129 // Compare with original value. | |
| 6130 __ cmpq(out, value); | |
| 6131 // Value cannot be held in Int32, deopt. | |
| 6132 __ j(NOT_EQUAL, deopt); | |
| 6133 } | |
| 5651 } else if (to() == kUnboxedMint) { | 6134 } else if (to() == kUnboxedMint) { |
| 5652 ASSERT((from() == kUnboxedUint32) || (from() == kUnboxedInt32)); | 6135 ASSERT((from() == kUnboxedUint32) || (from() == kUnboxedInt32)); |
| 5653 UNREACHABLE(); | 6136 const Register value = locs()->in(0).reg(); |
| 6137 const Register out = locs()->out(0).reg(); | |
| 6138 if (from() == kUnboxedUint32) { | |
| 6139 // Zero extend. | |
| 6140 __ movl(out, value); | |
| 6141 } else { | |
| 6142 // Sign extend. | |
| 6143 ASSERT(from() == kUnboxedInt32); | |
| 6144 __ movsxd(out, value); | |
| 6145 } | |
| 5654 } else { | 6146 } else { |
| 5655 UNREACHABLE(); | 6147 UNREACHABLE(); |
| 5656 } | 6148 } |
| 5657 } | 6149 } |
| 5658 | 6150 |
| 5659 | 6151 |
| 5660 LocationSummary* ThrowInstr::MakeLocationSummary(Isolate* isolate, | 6152 LocationSummary* ThrowInstr::MakeLocationSummary(Isolate* isolate, |
| 5661 bool opt) const { | 6153 bool opt) const { |
| 5662 return new(isolate) LocationSummary(isolate, 0, 0, LocationSummary::kCall); | 6154 return new(isolate) LocationSummary(isolate, 0, 0, LocationSummary::kCall); |
| 5663 } | 6155 } |
| (...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5927 __ movq(R10, Immediate(kInvalidObjectPointer)); | 6419 __ movq(R10, Immediate(kInvalidObjectPointer)); |
| 5928 __ movq(RBX, Immediate(kInvalidObjectPointer)); | 6420 __ movq(RBX, Immediate(kInvalidObjectPointer)); |
| 5929 #endif | 6421 #endif |
| 5930 } | 6422 } |
| 5931 | 6423 |
| 5932 } // namespace dart | 6424 } // namespace dart |
| 5933 | 6425 |
| 5934 #undef __ | 6426 #undef __ |
| 5935 | 6427 |
| 5936 #endif // defined TARGET_ARCH_X64 | 6428 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |