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 337 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 348 | 348 |
| 349 void AssertBooleanInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 349 void AssertBooleanInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 350 Register obj = locs()->in(0).reg(); | 350 Register obj = locs()->in(0).reg(); |
| 351 Register result = locs()->out(0).reg(); | 351 Register result = locs()->out(0).reg(); |
| 352 | 352 |
| 353 EmitAssertBoolean(obj, token_pos(), deopt_id(), locs(), compiler); | 353 EmitAssertBoolean(obj, token_pos(), deopt_id(), locs(), compiler); |
| 354 ASSERT(obj == result); | 354 ASSERT(obj == result); |
| 355 } | 355 } |
| 356 | 356 |
| 357 | 357 |
| 358 static Condition TokenKindToSmiCondition(Token::Kind kind) { | 358 static Condition TokenKindToIntCondition(Token::Kind kind) { |
| 359 switch (kind) { | 359 switch (kind) { |
| 360 case Token::kEQ: return EQUAL; | 360 case Token::kEQ: return EQUAL; |
| 361 case Token::kNE: return NOT_EQUAL; | 361 case Token::kNE: return NOT_EQUAL; |
| 362 case Token::kLT: return LESS; | 362 case Token::kLT: return LESS; |
| 363 case Token::kGT: return GREATER; | 363 case Token::kGT: return GREATER; |
| 364 case Token::kLTE: return LESS_EQUAL; | 364 case Token::kLTE: return LESS_EQUAL; |
| 365 case Token::kGTE: return GREATER_EQUAL; | 365 case Token::kGTE: return GREATER_EQUAL; |
| 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 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 451 __ j(false_condition, labels.false_label); | 460 __ j(false_condition, labels.false_label); |
| 452 | 461 |
| 453 // Fall through or jump to the true successor. | 462 // Fall through or jump to the true successor. |
| 454 if (labels.fall_through != labels.true_label) { | 463 if (labels.fall_through != labels.true_label) { |
| 455 __ jmp(labels.true_label); | 464 __ jmp(labels.true_label); |
| 456 } | 465 } |
| 457 } | 466 } |
| 458 } | 467 } |
| 459 | 468 |
| 460 | 469 |
| 461 static Condition EmitSmiComparisonOp(FlowGraphCompiler* compiler, | 470 static Condition EmitIntComparisonOp(FlowGraphCompiler* compiler, |
|
Vyacheslav Egorov (Google)
2014/10/07 12:03:50
Maybe it's better to call it Int64ComparisonOp to
| |
| 462 const LocationSummary& locs, | 471 const LocationSummary& locs, |
| 463 Token::Kind kind, | 472 Token::Kind kind, |
| 464 BranchLabels labels) { | 473 BranchLabels labels) { |
| 465 Location left = locs.in(0); | 474 Location left = locs.in(0); |
| 466 Location right = locs.in(1); | 475 Location right = locs.in(1); |
| 467 ASSERT(!left.IsConstant() || !right.IsConstant()); | 476 ASSERT(!left.IsConstant() || !right.IsConstant()); |
| 468 | 477 |
| 469 Condition true_condition = TokenKindToSmiCondition(kind); | 478 Condition true_condition = TokenKindToIntCondition(kind); |
| 470 | 479 |
| 471 if (left.IsConstant()) { | 480 if (left.IsConstant()) { |
| 472 __ CompareObject(right.reg(), left.constant(), PP); | 481 __ CompareObject(right.reg(), left.constant(), PP); |
| 473 true_condition = FlipCondition(true_condition); | 482 true_condition = FlipCondition(true_condition); |
| 474 } else if (right.IsConstant()) { | 483 } else if (right.IsConstant()) { |
| 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()); |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 509 Condition true_condition = TokenKindToDoubleCondition(kind); | 518 Condition true_condition = TokenKindToDoubleCondition(kind); |
| 510 Label* nan_result = (true_condition == NOT_EQUAL) | 519 Label* nan_result = (true_condition == NOT_EQUAL) |
| 511 ? labels.true_label : labels.false_label; | 520 ? labels.true_label : labels.false_label; |
| 512 __ j(PARITY_EVEN, nan_result); | 521 __ j(PARITY_EVEN, nan_result); |
| 513 return true_condition; | 522 return true_condition; |
| 514 } | 523 } |
| 515 | 524 |
| 516 | 525 |
| 517 Condition EqualityCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 526 Condition EqualityCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| 518 BranchLabels labels) { | 527 BranchLabels labels) { |
| 519 if (operation_cid() == kSmiCid) { | 528 if ((operation_cid() == kSmiCid) || (operation_cid() == kMintCid)) { |
| 520 return EmitSmiComparisonOp(compiler, *locs(), kind(), labels); | 529 return EmitIntComparisonOp(compiler, *locs(), kind(), labels); |
| 521 } else { | 530 } else { |
| 522 ASSERT(operation_cid() == kDoubleCid); | 531 ASSERT(operation_cid() == kDoubleCid); |
| 523 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); | 532 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); |
| 524 } | 533 } |
| 525 } | 534 } |
| 526 | 535 |
| 527 | 536 |
| 528 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 537 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 529 ASSERT((kind() == Token::kEQ) || (kind() == Token::kNE)); | 538 ASSERT((kind() == Token::kEQ) || (kind() == Token::kNE)); |
| 530 | 539 |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 676 bool opt) const { | 685 bool opt) const { |
| 677 const intptr_t kNumInputs = 2; | 686 const intptr_t kNumInputs = 2; |
| 678 const intptr_t kNumTemps = 0; | 687 const intptr_t kNumTemps = 0; |
| 679 if (operation_cid() == kDoubleCid) { | 688 if (operation_cid() == kDoubleCid) { |
| 680 LocationSummary* summary = new(isolate) LocationSummary( | 689 LocationSummary* summary = new(isolate) LocationSummary( |
| 681 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 690 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 682 summary->set_in(0, Location::RequiresFpuRegister()); | 691 summary->set_in(0, Location::RequiresFpuRegister()); |
| 683 summary->set_in(1, Location::RequiresFpuRegister()); | 692 summary->set_in(1, Location::RequiresFpuRegister()); |
| 684 summary->set_out(0, Location::RequiresRegister()); | 693 summary->set_out(0, Location::RequiresRegister()); |
| 685 return summary; | 694 return summary; |
| 695 } else if (operation_cid() == kMintCid) { | |
| 696 LocationSummary* summary = new(isolate) LocationSummary( | |
| 697 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | |
| 698 summary->set_in(0, Location::RequiresRegister()); | |
| 699 summary->set_in(1, Location::RequiresRegister()); | |
| 700 summary->set_out(0, Location::RequiresRegister()); | |
| 701 return summary; | |
| 686 } | 702 } |
| 687 ASSERT(operation_cid() == kSmiCid); | 703 ASSERT(operation_cid() == kSmiCid); |
| 688 LocationSummary* summary = new(isolate) LocationSummary( | 704 LocationSummary* summary = new(isolate) LocationSummary( |
| 689 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 705 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 690 summary->set_in(0, Location::RegisterOrConstant(left())); | 706 summary->set_in(0, Location::RegisterOrConstant(left())); |
| 691 // Only one input can be a constant operand. The case of two constant | 707 // Only one input can be a constant operand. The case of two constant |
| 692 // operands should be handled by constant propagation. | 708 // operands should be handled by constant propagation. |
| 693 summary->set_in(1, summary->in(0).IsConstant() | 709 summary->set_in(1, summary->in(0).IsConstant() |
| 694 ? Location::RequiresRegister() | 710 ? Location::RequiresRegister() |
| 695 : Location::RegisterOrConstant(right())); | 711 : Location::RegisterOrConstant(right())); |
| 696 summary->set_out(0, Location::RequiresRegister()); | 712 summary->set_out(0, Location::RequiresRegister()); |
| 697 return summary; | 713 return summary; |
| 698 } | 714 } |
| 699 | 715 |
| 700 | 716 |
| 701 Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 717 Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| 702 BranchLabels labels) { | 718 BranchLabels labels) { |
| 703 if (operation_cid() == kSmiCid) { | 719 if ((operation_cid() == kSmiCid) || (operation_cid() == kMintCid)) { |
| 704 return EmitSmiComparisonOp(compiler, *locs(), kind(), labels); | 720 return EmitIntComparisonOp(compiler, *locs(), kind(), labels); |
| 705 } else { | 721 } else { |
| 706 ASSERT(operation_cid() == kDoubleCid); | 722 ASSERT(operation_cid() == kDoubleCid); |
| 707 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); | 723 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); |
| 708 } | 724 } |
| 709 } | 725 } |
| 710 | 726 |
| 711 | 727 |
| 712 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 728 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 713 Label is_true, is_false; | 729 Label is_true, is_false; |
| 714 BranchLabels labels = { &is_true, &is_false, &is_false }; | 730 BranchLabels labels = { &is_true, &is_false, &is_false }; |
| (...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 941 case kExternalTypedDataUint8ArrayCid: | 957 case kExternalTypedDataUint8ArrayCid: |
| 942 case kExternalTypedDataUint8ClampedArrayCid: | 958 case kExternalTypedDataUint8ClampedArrayCid: |
| 943 case kTypedDataInt16ArrayCid: | 959 case kTypedDataInt16ArrayCid: |
| 944 case kTypedDataUint16ArrayCid: | 960 case kTypedDataUint16ArrayCid: |
| 945 case kOneByteStringCid: | 961 case kOneByteStringCid: |
| 946 case kTwoByteStringCid: | 962 case kTwoByteStringCid: |
| 947 case kTypedDataInt32ArrayCid: | 963 case kTypedDataInt32ArrayCid: |
| 948 case kTypedDataUint32ArrayCid: | 964 case kTypedDataUint32ArrayCid: |
| 949 return CompileType::FromCid(kSmiCid); | 965 return CompileType::FromCid(kSmiCid); |
| 950 | 966 |
| 967 case kTypedDataInt64ArrayCid: | |
| 968 return CompileType::Int(); | |
| 969 | |
| 951 default: | 970 default: |
| 952 UNIMPLEMENTED(); | 971 UNIMPLEMENTED(); |
| 953 return CompileType::Dynamic(); | 972 return CompileType::Dynamic(); |
| 954 } | 973 } |
| 955 } | 974 } |
| 956 | 975 |
| 957 | 976 |
| 958 Representation LoadIndexedInstr::representation() const { | 977 Representation LoadIndexedInstr::representation() const { |
| 959 switch (class_id_) { | 978 switch (class_id_) { |
| 960 case kArrayCid: | 979 case kArrayCid: |
| 961 case kImmutableArrayCid: | 980 case kImmutableArrayCid: |
| 962 case kTypedDataInt8ArrayCid: | 981 case kTypedDataInt8ArrayCid: |
| 963 case kTypedDataUint8ArrayCid: | 982 case kTypedDataUint8ArrayCid: |
| 964 case kTypedDataUint8ClampedArrayCid: | 983 case kTypedDataUint8ClampedArrayCid: |
| 965 case kExternalTypedDataUint8ArrayCid: | 984 case kExternalTypedDataUint8ArrayCid: |
| 966 case kExternalTypedDataUint8ClampedArrayCid: | 985 case kExternalTypedDataUint8ClampedArrayCid: |
| 967 case kTypedDataInt16ArrayCid: | 986 case kTypedDataInt16ArrayCid: |
| 968 case kTypedDataUint16ArrayCid: | 987 case kTypedDataUint16ArrayCid: |
| 969 case kOneByteStringCid: | 988 case kOneByteStringCid: |
| 970 case kTwoByteStringCid: | 989 case kTwoByteStringCid: |
| 971 case kTypedDataInt32ArrayCid: | 990 case kTypedDataInt32ArrayCid: |
| 972 case kTypedDataUint32ArrayCid: | 991 case kTypedDataUint32ArrayCid: |
| 973 return kTagged; | 992 return kTagged; |
| 993 case kTypedDataInt64ArrayCid: | |
| 994 return kUnboxedMint; | |
| 974 case kTypedDataFloat32ArrayCid: | 995 case kTypedDataFloat32ArrayCid: |
| 975 case kTypedDataFloat64ArrayCid: | 996 case kTypedDataFloat64ArrayCid: |
| 976 return kUnboxedDouble; | 997 return kUnboxedDouble; |
| 977 case kTypedDataInt32x4ArrayCid: | 998 case kTypedDataInt32x4ArrayCid: |
| 978 return kUnboxedInt32x4; | 999 return kUnboxedInt32x4; |
| 979 case kTypedDataFloat32x4ArrayCid: | 1000 case kTypedDataFloat32x4ArrayCid: |
| 980 return kUnboxedFloat32x4; | 1001 return kUnboxedFloat32x4; |
| 981 case kTypedDataFloat64x2ArrayCid: | 1002 case kTypedDataFloat64x2ArrayCid: |
| 982 return kUnboxedFloat64x2; | 1003 return kUnboxedFloat64x2; |
| 983 default: | 1004 default: |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1079 __ SmiTag(result); | 1100 __ SmiTag(result); |
| 1080 break; | 1101 break; |
| 1081 case kTypedDataInt32ArrayCid: | 1102 case kTypedDataInt32ArrayCid: |
| 1082 __ movsxd(result, element_address); | 1103 __ movsxd(result, element_address); |
| 1083 __ SmiTag(result); | 1104 __ SmiTag(result); |
| 1084 break; | 1105 break; |
| 1085 case kTypedDataUint32ArrayCid: | 1106 case kTypedDataUint32ArrayCid: |
| 1086 __ movl(result, element_address); | 1107 __ movl(result, element_address); |
| 1087 __ SmiTag(result); | 1108 __ SmiTag(result); |
| 1088 break; | 1109 break; |
| 1110 case kTypedDataInt64ArrayCid: | |
| 1111 __ movq(result, element_address); | |
| 1112 break; | |
| 1089 default: | 1113 default: |
| 1090 ASSERT((class_id() == kArrayCid) || (class_id() == kImmutableArrayCid)); | 1114 ASSERT((class_id() == kArrayCid) || (class_id() == kImmutableArrayCid)); |
| 1091 __ movq(result, element_address); | 1115 __ movq(result, element_address); |
| 1092 break; | 1116 break; |
| 1093 } | 1117 } |
| 1094 } | 1118 } |
| 1095 | 1119 |
| 1096 | 1120 |
| 1097 Representation StoreIndexedInstr::RequiredInputRepresentation( | 1121 Representation StoreIndexedInstr::RequiredInputRepresentation( |
| 1098 intptr_t idx) const { | 1122 intptr_t idx) const { |
| 1099 if (idx == 0) return kNoRepresentation; | 1123 if (idx == 0) return kNoRepresentation; |
| 1100 if (idx == 1) return kTagged; | 1124 if (idx == 1) return kTagged; |
| 1101 ASSERT(idx == 2); | 1125 ASSERT(idx == 2); |
| 1102 switch (class_id_) { | 1126 switch (class_id_) { |
| 1103 case kArrayCid: | 1127 case kArrayCid: |
| 1104 case kOneByteStringCid: | 1128 case kOneByteStringCid: |
| 1105 case kTypedDataInt8ArrayCid: | 1129 case kTypedDataInt8ArrayCid: |
| 1106 case kTypedDataUint8ArrayCid: | 1130 case kTypedDataUint8ArrayCid: |
| 1107 case kExternalTypedDataUint8ArrayCid: | 1131 case kExternalTypedDataUint8ArrayCid: |
| 1108 case kTypedDataUint8ClampedArrayCid: | 1132 case kTypedDataUint8ClampedArrayCid: |
| 1109 case kExternalTypedDataUint8ClampedArrayCid: | 1133 case kExternalTypedDataUint8ClampedArrayCid: |
| 1110 case kTypedDataInt16ArrayCid: | 1134 case kTypedDataInt16ArrayCid: |
| 1111 case kTypedDataUint16ArrayCid: | 1135 case kTypedDataUint16ArrayCid: |
| 1112 return kTagged; | 1136 return kTagged; |
| 1113 case kTypedDataInt32ArrayCid: | 1137 case kTypedDataInt32ArrayCid: |
| 1114 return kUnboxedInt32; | 1138 return kUnboxedInt32; |
| 1115 case kTypedDataUint32ArrayCid: | 1139 case kTypedDataUint32ArrayCid: |
| 1116 return kUnboxedUint32; | 1140 return kUnboxedUint32; |
| 1141 case kTypedDataInt64ArrayCid: | |
| 1142 return kUnboxedMint; | |
| 1117 case kTypedDataFloat32ArrayCid: | 1143 case kTypedDataFloat32ArrayCid: |
| 1118 case kTypedDataFloat64ArrayCid: | 1144 case kTypedDataFloat64ArrayCid: |
| 1119 return kUnboxedDouble; | 1145 return kUnboxedDouble; |
| 1120 case kTypedDataFloat32x4ArrayCid: | 1146 case kTypedDataFloat32x4ArrayCid: |
| 1121 return kUnboxedFloat32x4; | 1147 return kUnboxedFloat32x4; |
| 1122 case kTypedDataInt32x4ArrayCid: | 1148 case kTypedDataInt32x4ArrayCid: |
| 1123 return kUnboxedInt32x4; | 1149 return kUnboxedInt32x4; |
| 1124 case kTypedDataFloat64x2ArrayCid: | 1150 case kTypedDataFloat64x2ArrayCid: |
| 1125 return kUnboxedFloat64x2; | 1151 return kUnboxedFloat64x2; |
| 1126 default: | 1152 default: |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1164 // RBX, RCX, RDX) instead of using a fixed register. | 1190 // RBX, RCX, RDX) instead of using a fixed register. |
| 1165 locs->set_in(2, Location::FixedRegisterOrSmiConstant(value(), RAX)); | 1191 locs->set_in(2, Location::FixedRegisterOrSmiConstant(value(), RAX)); |
| 1166 break; | 1192 break; |
| 1167 case kTypedDataInt16ArrayCid: | 1193 case kTypedDataInt16ArrayCid: |
| 1168 case kTypedDataUint16ArrayCid: | 1194 case kTypedDataUint16ArrayCid: |
| 1169 case kTypedDataInt32ArrayCid: | 1195 case kTypedDataInt32ArrayCid: |
| 1170 case kTypedDataUint32ArrayCid: | 1196 case kTypedDataUint32ArrayCid: |
| 1171 // Writable register because the value must be untagged before storing. | 1197 // Writable register because the value must be untagged before storing. |
| 1172 locs->set_in(2, Location::WritableRegister()); | 1198 locs->set_in(2, Location::WritableRegister()); |
| 1173 break; | 1199 break; |
| 1200 case kTypedDataInt64ArrayCid: | |
| 1201 locs->set_in(2, Location::RequiresRegister()); | |
| 1202 break; | |
| 1174 case kTypedDataFloat32ArrayCid: | 1203 case kTypedDataFloat32ArrayCid: |
| 1175 case kTypedDataFloat64ArrayCid: | 1204 case kTypedDataFloat64ArrayCid: |
| 1176 // TODO(srdjan): Support Float64 constants. | 1205 // TODO(srdjan): Support Float64 constants. |
| 1177 locs->set_in(2, Location::RequiresFpuRegister()); | 1206 locs->set_in(2, Location::RequiresFpuRegister()); |
| 1178 break; | 1207 break; |
| 1179 case kTypedDataInt32x4ArrayCid: | 1208 case kTypedDataInt32x4ArrayCid: |
| 1180 case kTypedDataFloat64x2ArrayCid: | 1209 case kTypedDataFloat64x2ArrayCid: |
| 1181 case kTypedDataFloat32x4ArrayCid: | 1210 case kTypedDataFloat32x4ArrayCid: |
| 1182 locs->set_in(2, Location::RequiresFpuRegister()); | 1211 locs->set_in(2, Location::RequiresFpuRegister()); |
| 1183 break; | 1212 break; |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1265 case kTypedDataUint16ArrayCid: { | 1294 case kTypedDataUint16ArrayCid: { |
| 1266 Register value = locs()->in(2).reg(); | 1295 Register value = locs()->in(2).reg(); |
| 1267 __ SmiUntag(value); | 1296 __ SmiUntag(value); |
| 1268 __ movw(element_address, value); | 1297 __ movw(element_address, value); |
| 1269 break; | 1298 break; |
| 1270 } | 1299 } |
| 1271 case kTypedDataInt32ArrayCid: | 1300 case kTypedDataInt32ArrayCid: |
| 1272 case kTypedDataUint32ArrayCid: { | 1301 case kTypedDataUint32ArrayCid: { |
| 1273 Register value = locs()->in(2).reg(); | 1302 Register value = locs()->in(2).reg(); |
| 1274 __ movl(element_address, value); | 1303 __ movl(element_address, value); |
| 1275 break; | 1304 break; |
| 1305 } | |
| 1306 case kTypedDataInt64ArrayCid: { | |
| 1307 Register value = locs()->in(2).reg(); | |
| 1308 __ movq(element_address, value); | |
| 1309 break; | |
| 1276 } | 1310 } |
| 1277 case kTypedDataFloat32ArrayCid: | 1311 case kTypedDataFloat32ArrayCid: |
| 1278 __ movss(element_address, locs()->in(2).fpu_reg()); | 1312 __ movss(element_address, locs()->in(2).fpu_reg()); |
| 1279 break; | 1313 break; |
| 1280 case kTypedDataFloat64ArrayCid: | 1314 case kTypedDataFloat64ArrayCid: |
| 1281 __ movsd(element_address, locs()->in(2).fpu_reg()); | 1315 __ movsd(element_address, locs()->in(2).fpu_reg()); |
| 1282 break; | 1316 break; |
| 1283 case kTypedDataInt32x4ArrayCid: | 1317 case kTypedDataInt32x4ArrayCid: |
| 1284 case kTypedDataFloat64x2ArrayCid: | 1318 case kTypedDataFloat64x2ArrayCid: |
| 1285 case kTypedDataFloat32x4ArrayCid: | 1319 case kTypedDataFloat32x4ArrayCid: |
| (...skipping 4147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5433 Register length = length_loc.reg(); | 5467 Register length = length_loc.reg(); |
| 5434 Register index = index_loc.reg(); | 5468 Register index = index_loc.reg(); |
| 5435 __ cmpq(index, length); | 5469 __ cmpq(index, length); |
| 5436 __ j(ABOVE_EQUAL, deopt); | 5470 __ j(ABOVE_EQUAL, deopt); |
| 5437 } | 5471 } |
| 5438 } | 5472 } |
| 5439 | 5473 |
| 5440 | 5474 |
| 5441 LocationSummary* UnboxIntegerInstr::MakeLocationSummary(Isolate* isolate, | 5475 LocationSummary* UnboxIntegerInstr::MakeLocationSummary(Isolate* isolate, |
| 5442 bool opt) const { | 5476 bool opt) const { |
| 5443 UNIMPLEMENTED(); | 5477 const intptr_t kNumInputs = 1; |
| 5444 return NULL; | 5478 const intptr_t kNumTemps = 0; |
| 5479 LocationSummary* locs = new(isolate) LocationSummary( | |
| 5480 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | |
| 5481 locs->set_in(0, Location::RequiresRegister()); | |
| 5482 locs->set_out(0, Location::SameAsFirstInput()); | |
| 5483 return locs; | |
| 5445 } | 5484 } |
| 5446 | 5485 |
| 5447 | 5486 |
| 5448 void UnboxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5487 void UnboxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5449 UNIMPLEMENTED(); | 5488 const intptr_t value_cid = value()->Type()->ToCid(); |
| 5489 const Register value = locs()->in(0).reg(); | |
| 5490 const Register result = locs()->out(0).reg(); | |
| 5491 ASSERT(value == result); | |
| 5492 | |
| 5493 if (value_cid == kMintCid) { | |
| 5494 __ movq(result, FieldAddress(value, Mint::value_offset())); | |
| 5495 } else if (value_cid == kSmiCid) { | |
| 5496 __ SmiUntag(result); | |
| 5497 } else { | |
| 5498 Label* deopt = compiler->AddDeoptStub(deopt_id_, | |
| 5499 ICData::kDeoptUnboxInteger); | |
| 5500 Label done; | |
| 5501 __ SmiUntagOrCheckClass(value, kMintCid, &done); | |
| 5502 __ j(NOT_EQUAL, deopt); | |
| 5503 // Undo untagging by multiplying value with 2. | |
| 5504 __ movq(result, Address(value, TIMES_2, Mint::value_offset())); | |
| 5505 __ Bind(&done); | |
| 5506 } | |
| 5450 } | 5507 } |
| 5451 | 5508 |
| 5452 | 5509 |
| 5453 LocationSummary* BoxIntegerInstr::MakeLocationSummary(Isolate* isolate, | 5510 LocationSummary* BoxIntegerInstr::MakeLocationSummary(Isolate* isolate, |
| 5454 bool opt) const { | 5511 bool opt) const { |
| 5455 UNIMPLEMENTED(); | 5512 const intptr_t kNumInputs = 1; |
| 5456 return NULL; | 5513 const intptr_t kNumTemps = 0; |
| 5514 LocationSummary* summary = new(isolate) LocationSummary( | |
| 5515 isolate, kNumInputs, kNumTemps, is_smi() | |
| 5516 ? LocationSummary::kNoCall | |
| 5517 : LocationSummary::kCallOnSlowPath); | |
| 5518 summary->set_in(0, Location::RequiresRegister()); | |
| 5519 summary->set_out(0, Location::RequiresRegister()); | |
| 5520 return summary; | |
| 5457 } | 5521 } |
| 5458 | 5522 |
| 5459 | 5523 |
| 5460 void BoxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5524 void BoxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5461 UNIMPLEMENTED(); | 5525 const Register out = locs()->out(0).reg(); |
| 5526 const Register value = locs()->in(0).reg(); | |
| 5527 | |
| 5528 if (is_smi()) { | |
| 5529 __ movq(out, value); | |
| 5530 __ SmiTag(out); | |
| 5531 return; | |
| 5532 } | |
| 5533 | |
| 5534 Label is_smi; | |
| 5535 Label done; | |
| 5536 __ movq(out, value); | |
| 5537 __ SmiTag(out); // shrl sets OF := SF ^ CF on 1 bit shifts | |
|
Vyacheslav Egorov (Google)
2014/10/07 12:03:50
I had a typo in this comment, sorry. It's tagging
| |
| 5538 __ j(NO_OVERFLOW, &done); | |
| 5539 BoxAllocationSlowPath::Allocate( | |
| 5540 compiler, this, compiler->mint_class(), out); | |
| 5541 __ movq(FieldAddress(out, Mint::value_offset()), value); | |
| 5542 __ Bind(&done); | |
| 5543 } | |
| 5544 | |
| 5545 | |
| 5546 template<typename OperandType> | |
| 5547 static void EmitInt64Arithmetic(FlowGraphCompiler* compiler, | |
| 5548 Token::Kind op_kind, | |
| 5549 Register left, | |
| 5550 const OperandType& right, | |
| 5551 Label* deopt) { | |
| 5552 switch (op_kind) { | |
| 5553 case Token::kADD: | |
| 5554 __ addq(left, right); | |
| 5555 break; | |
| 5556 case Token::kSUB: | |
| 5557 __ subq(left, right); | |
| 5558 break; | |
| 5559 case Token::kBIT_AND: | |
| 5560 __ andq(left, right); | |
| 5561 break; | |
| 5562 case Token::kBIT_OR: | |
| 5563 __ orq(left, right); | |
| 5564 break; | |
| 5565 case Token::kBIT_XOR: | |
| 5566 __ xorq(left, right); | |
| 5567 break; | |
| 5568 case Token::kMUL: | |
| 5569 __ imulq(left, right); | |
| 5570 break; | |
| 5571 default: | |
| 5572 UNREACHABLE(); | |
| 5573 } | |
| 5574 if (deopt != NULL) __ j(OVERFLOW, deopt); | |
| 5462 } | 5575 } |
| 5463 | 5576 |
| 5464 | 5577 |
| 5465 LocationSummary* BinaryMintOpInstr::MakeLocationSummary(Isolate* isolate, | 5578 LocationSummary* BinaryMintOpInstr::MakeLocationSummary(Isolate* isolate, |
| 5466 bool opt) const { | 5579 bool opt) const { |
| 5467 UNIMPLEMENTED(); | 5580 const intptr_t kNumInputs = 2; |
| 5468 return NULL; | 5581 const intptr_t kNumTemps = 0; |
| 5582 LocationSummary* summary = new(isolate) LocationSummary( | |
| 5583 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | |
| 5584 summary->set_in(0, Location::RequiresRegister()); | |
| 5585 summary->set_in(1, Location::RequiresRegister()); | |
| 5586 summary->set_out(0, Location::SameAsFirstInput()); | |
| 5587 return summary; | |
| 5469 } | 5588 } |
| 5470 | 5589 |
| 5471 | 5590 |
| 5472 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5591 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5473 UNIMPLEMENTED(); | 5592 const Register left = locs()->in(0).reg(); |
| 5593 const Register right = locs()->in(1).reg(); | |
| 5594 const Register out = locs()->out(0).reg(); | |
| 5595 | |
| 5596 ASSERT(out == left); | |
| 5597 | |
| 5598 Label* deopt = NULL; | |
| 5599 if (CanDeoptimize()) { | |
| 5600 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp); | |
| 5601 } | |
| 5602 | |
| 5603 EmitInt64Arithmetic(compiler, op_kind(), left, right, deopt); | |
| 5604 | |
| 5605 if (FLAG_throw_on_javascript_int_overflow) { | |
| 5606 EmitJavascriptOverflowCheck(compiler, range(), deopt, out); | |
| 5607 } | |
| 5474 } | 5608 } |
| 5475 | 5609 |
| 5476 | 5610 |
| 5477 LocationSummary* UnaryMintOpInstr::MakeLocationSummary(Isolate* isolate, | 5611 LocationSummary* UnaryMintOpInstr::MakeLocationSummary(Isolate* isolate, |
| 5478 bool opt) const { | 5612 bool opt) const { |
| 5479 UNIMPLEMENTED(); | 5613 const intptr_t kNumInputs = 1; |
| 5480 return NULL; | 5614 const intptr_t kNumTemps = 0; |
| 5615 LocationSummary* summary = new(isolate) LocationSummary( | |
| 5616 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | |
| 5617 summary->set_in(0, Location::RequiresRegister()); | |
| 5618 summary->set_out(0, Location::SameAsFirstInput()); | |
| 5619 return summary; | |
| 5481 } | 5620 } |
| 5482 | 5621 |
| 5483 | 5622 |
| 5484 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5623 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5485 UNIMPLEMENTED(); | 5624 ASSERT(op_kind() == Token::kBIT_NOT); |
| 5486 } | 5625 const Register left = locs()->in(0).reg(); |
| 5487 | 5626 const Register out = locs()->out(0).reg(); |
| 5627 ASSERT(out == left); | |
| 5628 | |
| 5629 Label* deopt = NULL; | |
| 5630 if (FLAG_throw_on_javascript_int_overflow) { | |
| 5631 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryMintOp); | |
| 5632 } | |
| 5633 | |
| 5634 __ notq(left); | |
| 5635 | |
| 5636 if (FLAG_throw_on_javascript_int_overflow) { | |
| 5637 EmitJavascriptOverflowCheck(compiler, range(), deopt, out); | |
| 5638 } | |
| 5639 } | |
| 5640 | |
| 5641 | |
| 5642 static const intptr_t kMintShiftCountLimit = 63; | |
| 5488 | 5643 |
| 5489 bool ShiftMintOpInstr::has_shift_count_check() const { | 5644 bool ShiftMintOpInstr::has_shift_count_check() const { |
| 5490 UNREACHABLE(); | 5645 return !RangeUtils::IsWithin( |
| 5491 return false; | 5646 right()->definition()->range(), 0, kMintShiftCountLimit); |
| 5492 } | 5647 } |
| 5493 | 5648 |
| 5494 | 5649 |
| 5495 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(Isolate* isolate, | 5650 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(Isolate* isolate, |
| 5496 bool opt) const { | 5651 bool opt) const { |
| 5497 UNIMPLEMENTED(); | 5652 const intptr_t kNumInputs = 2; |
| 5498 return NULL; | 5653 const intptr_t kNumTemps = can_overflow() ? 1 : 0; |
| 5654 LocationSummary* summary = new(isolate) LocationSummary( | |
| 5655 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | |
| 5656 summary->set_in(0, Location::RequiresRegister()); | |
| 5657 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), RCX)); | |
| 5658 if (kNumTemps > 0) { | |
| 5659 summary->set_temp(0, Location::RequiresRegister()); | |
| 5660 } | |
| 5661 summary->set_out(0, Location::SameAsFirstInput()); | |
| 5662 return summary; | |
| 5499 } | 5663 } |
| 5500 | 5664 |
| 5501 | 5665 |
| 5502 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5666 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5503 UNIMPLEMENTED(); | 5667 const Register left = locs()->in(0).reg(); |
| 5504 } | 5668 const Register out = locs()->out(0).reg(); |
| 5505 | 5669 ASSERT(left == out); |
| 5506 | 5670 |
| 5671 Label* deopt = NULL; | |
| 5672 if (CanDeoptimize()) { | |
| 5673 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptShiftMintOp); | |
| 5674 } | |
| 5675 if (locs()->in(1).IsConstant()) { | |
| 5676 // Code for a constant shift amount. | |
| 5677 ASSERT(locs()->in(1).constant().IsSmi()); | |
| 5678 const int64_t shift = | |
| 5679 reinterpret_cast<int64_t>(locs()->in(1).constant().raw()) >> 1; | |
| 5680 switch (op_kind()) { | |
| 5681 case Token::kSHR: | |
| 5682 __ sarq(left, Immediate(shift)); | |
| 5683 break; | |
| 5684 case Token::kSHL: { | |
| 5685 if (can_overflow()) { | |
| 5686 // Check for overflow. | |
| 5687 Register temp = locs()->temp(0).reg(); | |
| 5688 __ movq(temp, left); | |
| 5689 __ shlq(left, Immediate(shift)); | |
| 5690 __ sarq(left, Immediate(shift)); | |
| 5691 __ cmpq(left, temp); | |
| 5692 __ j(NOT_EQUAL, deopt); // Overflow. | |
| 5693 } | |
| 5694 // Shift for result now we know there is no overflow. | |
| 5695 __ shlq(left, Immediate(shift)); | |
| 5696 break; | |
| 5697 } | |
| 5698 default: | |
| 5699 UNREACHABLE(); | |
| 5700 } | |
| 5701 } else { | |
| 5702 // Code for a variable shift amount. | |
| 5703 // Deoptimize if shift count is > 63. | |
| 5704 // sarl operation masks the count to 5 bits and | |
| 5705 // shrd is undefined with count > operand size (32) | |
| 5706 __ SmiUntag(RCX); | |
| 5707 if (has_shift_count_check()) { | |
| 5708 __ cmpq(RCX, Immediate(kMintShiftCountLimit)); | |
| 5709 __ j(ABOVE, deopt); | |
| 5710 } | |
| 5711 Label done, large_shift; | |
| 5712 switch (op_kind()) { | |
| 5713 case Token::kSHR: { | |
| 5714 __ sarq(left, RCX); | |
| 5715 break; | |
| 5716 } | |
| 5717 case Token::kSHL: { | |
| 5718 if (can_overflow()) { | |
| 5719 // Check for overflow. | |
| 5720 Register temp = locs()->temp(0).reg(); | |
| 5721 __ movq(temp, left); | |
| 5722 __ shlq(left, RCX); | |
| 5723 __ sarq(left, RCX); | |
| 5724 __ cmpq(left, temp); | |
| 5725 __ j(NOT_EQUAL, deopt); // Overflow. | |
| 5726 } | |
| 5727 // Shift for result now we know there is no overflow. | |
| 5728 __ shlq(left, RCX); | |
| 5729 break; | |
| 5730 } | |
| 5731 default: | |
| 5732 UNREACHABLE(); | |
| 5733 } | |
| 5734 } | |
| 5735 if (FLAG_throw_on_javascript_int_overflow) { | |
| 5736 EmitJavascriptOverflowCheck(compiler, range(), deopt, out); | |
| 5737 } | |
| 5738 } | |
| 5739 | |
| 5740 | |
| 5507 CompileType BinaryUint32OpInstr::ComputeType() const { | 5741 CompileType BinaryUint32OpInstr::ComputeType() const { |
| 5508 return CompileType::FromCid(kSmiCid); | 5742 return CompileType::FromCid(kSmiCid); |
| 5509 } | 5743 } |
| 5510 | 5744 |
| 5511 | 5745 |
| 5512 CompileType ShiftUint32OpInstr::ComputeType() const { | 5746 CompileType ShiftUint32OpInstr::ComputeType() const { |
| 5513 return CompileType::FromCid(kSmiCid); | 5747 return CompileType::FromCid(kSmiCid); |
| 5514 } | 5748 } |
| 5515 | 5749 |
| 5516 | 5750 |
| 5517 CompileType UnaryUint32OpInstr::ComputeType() const { | 5751 CompileType UnaryUint32OpInstr::ComputeType() const { |
| 5518 return CompileType::FromCid(kSmiCid); | 5752 return CompileType::FromCid(kSmiCid); |
| 5519 } | 5753 } |
| 5520 | 5754 |
| 5521 | 5755 |
| 5522 DEFINE_UNIMPLEMENTED_INSTRUCTION(BinaryUint32OpInstr) | 5756 LocationSummary* BinaryUint32OpInstr::MakeLocationSummary(Isolate* isolate, |
| 5523 DEFINE_UNIMPLEMENTED_INSTRUCTION(ShiftUint32OpInstr) | 5757 bool opt) const { |
| 5524 DEFINE_UNIMPLEMENTED_INSTRUCTION(UnaryUint32OpInstr) | 5758 const intptr_t kNumInputs = 2; |
| 5759 const intptr_t kNumTemps = (op_kind() == Token::kMUL) ? 1 : 0; | |
| 5760 LocationSummary* summary = new(isolate) LocationSummary( | |
| 5761 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | |
| 5762 summary->set_in(0, Location::RequiresRegister()); | |
| 5763 summary->set_in(1, Location::RequiresRegister()); | |
| 5764 summary->set_out(0, Location::SameAsFirstInput()); | |
| 5765 return summary; | |
| 5766 } | |
| 5767 | |
| 5768 | |
| 5769 template<typename OperandType> | |
| 5770 static void EmitIntegerArithmetic(FlowGraphCompiler* compiler, | |
| 5771 Token::Kind op_kind, | |
| 5772 Register left, | |
| 5773 const OperandType& right, | |
| 5774 Label* deopt) { | |
| 5775 switch (op_kind) { | |
| 5776 case Token::kADD: | |
| 5777 __ addl(left, right); | |
| 5778 break; | |
| 5779 case Token::kSUB: | |
| 5780 __ subl(left, right); | |
| 5781 break; | |
| 5782 case Token::kBIT_AND: | |
| 5783 __ andl(left, right); | |
| 5784 break; | |
| 5785 case Token::kBIT_OR: | |
| 5786 __ orl(left, right); | |
| 5787 break; | |
| 5788 case Token::kBIT_XOR: | |
| 5789 __ xorl(left, right); | |
| 5790 break; | |
| 5791 case Token::kMUL: | |
| 5792 __ imull(left, right); | |
| 5793 break; | |
| 5794 default: | |
| 5795 UNREACHABLE(); | |
| 5796 } | |
| 5797 if (deopt != NULL) __ j(OVERFLOW, deopt); | |
| 5798 } | |
| 5799 | |
| 5800 | |
| 5801 void BinaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 5802 Register left = locs()->in(0).reg(); | |
| 5803 Register right = locs()->in(1).reg(); | |
| 5804 Register out = locs()->out(0).reg(); | |
| 5805 ASSERT(out == left); | |
| 5806 switch (op_kind()) { | |
| 5807 case Token::kBIT_AND: | |
| 5808 case Token::kBIT_OR: | |
| 5809 case Token::kBIT_XOR: | |
| 5810 case Token::kADD: | |
| 5811 case Token::kSUB: | |
| 5812 case Token::kMUL: | |
| 5813 EmitIntegerArithmetic(compiler, op_kind(), left, right, NULL); | |
| 5814 return; | |
| 5815 default: | |
| 5816 UNREACHABLE(); | |
| 5817 } | |
| 5818 } | |
| 5819 | |
| 5820 | |
| 5821 LocationSummary* ShiftUint32OpInstr::MakeLocationSummary(Isolate* isolate, | |
| 5822 bool opt) const { | |
| 5823 const intptr_t kNumInputs = 2; | |
| 5824 const intptr_t kNumTemps = 0; | |
| 5825 LocationSummary* summary = new(isolate) LocationSummary( | |
| 5826 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | |
| 5827 summary->set_in(0, Location::RequiresRegister()); | |
| 5828 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), RCX)); | |
| 5829 summary->set_out(0, Location::SameAsFirstInput()); | |
| 5830 return summary; | |
| 5831 } | |
| 5832 | |
| 5833 | |
| 5834 void ShiftUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 5835 const intptr_t kShifterLimit = 31; | |
| 5836 | |
| 5837 Register left = locs()->in(0).reg(); | |
| 5838 Register out = locs()->out(0).reg(); | |
| 5839 ASSERT(left == out); | |
| 5840 | |
| 5841 | |
| 5842 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptShiftMintOp); | |
| 5843 | |
| 5844 if (locs()->in(1).IsConstant()) { | |
| 5845 // Shifter is constant. | |
| 5846 | |
| 5847 const Object& constant = locs()->in(1).constant(); | |
| 5848 ASSERT(constant.IsSmi()); | |
| 5849 const intptr_t shift_value = Smi::Cast(constant).Value(); | |
| 5850 | |
| 5851 // Check constant shift value. | |
| 5852 if (shift_value > kShifterLimit) { | |
|
Vyacheslav Egorov (Google)
2014/10/07 12:03:50
Is this not handled in Canonicalize?
Cutch
2014/10/21 17:42:11
Done.
| |
| 5853 // Result is 0. | |
| 5854 __ xorq(left, left); | |
| 5855 } else { | |
| 5856 // Do the shift: (shift_value > 0) && (shift_value <= kShifterLimit). | |
| 5857 switch (op_kind()) { | |
| 5858 case Token::kSHR: | |
| 5859 __ shrl(left, Immediate(shift_value)); | |
| 5860 break; | |
| 5861 case Token::kSHL: | |
| 5862 __ shll(left, Immediate(shift_value)); | |
| 5863 break; | |
| 5864 default: | |
| 5865 UNREACHABLE(); | |
| 5866 } | |
| 5867 } | |
| 5868 return; | |
| 5869 } | |
| 5870 | |
| 5871 // Non constant shift value. | |
| 5872 | |
| 5873 Register shifter = locs()->in(1).reg(); | |
| 5874 ASSERT(shifter == RCX); | |
| 5875 | |
| 5876 Label done; | |
| 5877 Label zero; | |
| 5878 | |
| 5879 // TODO(johnmccutchan): Use range information to avoid these checks. | |
| 5880 __ SmiUntag(shifter); | |
| 5881 __ cmpq(shifter, Immediate(0)); | |
| 5882 // If shift value is < 0, deoptimize. | |
| 5883 __ j(NEGATIVE, deopt); | |
| 5884 __ cmpq(shifter, Immediate(kShifterLimit)); | |
| 5885 // If shift value is >= 32, return zero. | |
| 5886 __ j(ABOVE, &zero); | |
| 5887 | |
| 5888 // Do the shift. | |
| 5889 switch (op_kind()) { | |
| 5890 case Token::kSHR: | |
| 5891 __ shrl(left, shifter); | |
| 5892 __ jmp(&done); | |
| 5893 break; | |
| 5894 case Token::kSHL: | |
| 5895 __ shll(left, shifter); | |
| 5896 __ jmp(&done); | |
| 5897 break; | |
| 5898 default: | |
| 5899 UNREACHABLE(); | |
| 5900 } | |
| 5901 | |
| 5902 __ Bind(&zero); | |
| 5903 // Shift was greater than 31 bits, just return zero. | |
| 5904 __ xorq(left, left); | |
| 5905 | |
| 5906 // Exit path. | |
| 5907 __ Bind(&done); | |
| 5908 } | |
| 5909 | |
| 5910 | |
| 5911 LocationSummary* UnaryUint32OpInstr::MakeLocationSummary(Isolate* isolate, | |
| 5912 bool opt) const { | |
| 5913 const intptr_t kNumInputs = 1; | |
| 5914 const intptr_t kNumTemps = 0; | |
| 5915 LocationSummary* summary = new(isolate) LocationSummary( | |
| 5916 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | |
| 5917 summary->set_in(0, Location::RequiresRegister()); | |
| 5918 summary->set_out(0, Location::SameAsFirstInput()); | |
| 5919 return summary; | |
| 5920 } | |
| 5921 | |
| 5922 | |
| 5923 void UnaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 5924 Register out = locs()->out(0).reg(); | |
| 5925 ASSERT(locs()->in(0).reg() == out); | |
| 5926 | |
| 5927 ASSERT(op_kind() == Token::kBIT_NOT); | |
| 5928 | |
| 5929 __ notl(out); | |
| 5930 } | |
| 5931 | |
| 5932 | |
| 5525 DEFINE_UNIMPLEMENTED_INSTRUCTION(BinaryInt32OpInstr) | 5933 DEFINE_UNIMPLEMENTED_INSTRUCTION(BinaryInt32OpInstr) |
| 5526 | 5934 |
| 5527 | 5935 |
| 5528 LocationSummary* UnboxIntNInstr::MakeLocationSummary(Isolate* isolate, | 5936 LocationSummary* UnboxIntNInstr::MakeLocationSummary(Isolate* isolate, |
| 5529 bool opt) const { | 5937 bool opt) const { |
| 5530 const intptr_t kNumInputs = 1; | 5938 const intptr_t kNumInputs = 1; |
| 5531 const intptr_t kNumTemps = (!is_truncating() && CanDeoptimize()) ? 1 : 0; | 5939 const intptr_t kNumTemps = (!is_truncating() && CanDeoptimize()) ? 1 : 0; |
| 5532 LocationSummary* summary = new(isolate) LocationSummary( | 5940 LocationSummary* summary = new(isolate) LocationSummary( |
| 5533 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5941 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5534 summary->set_in(0, Location::RequiresRegister()); | 5942 summary->set_in(0, Location::RequiresRegister()); |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5606 } | 6014 } |
| 5607 | 6015 |
| 5608 | 6016 |
| 5609 LocationSummary* UnboxedIntConverterInstr::MakeLocationSummary(Isolate* isolate, | 6017 LocationSummary* UnboxedIntConverterInstr::MakeLocationSummary(Isolate* isolate, |
| 5610 bool opt) const { | 6018 bool opt) const { |
| 5611 const intptr_t kNumInputs = 1; | 6019 const intptr_t kNumInputs = 1; |
| 5612 const intptr_t kNumTemps = 0; | 6020 const intptr_t kNumTemps = 0; |
| 5613 LocationSummary* summary = new(isolate) LocationSummary( | 6021 LocationSummary* summary = new(isolate) LocationSummary( |
| 5614 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6022 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5615 if (from() == kUnboxedMint) { | 6023 if (from() == kUnboxedMint) { |
| 5616 UNREACHABLE(); | 6024 ASSERT((to() == kUnboxedUint32) || (to() == kUnboxedInt32)); |
| 6025 summary->set_in(0, Location::RequiresRegister()); | |
| 6026 summary->set_out(0, Location::SameAsFirstInput()); | |
| 5617 } else if (to() == kUnboxedMint) { | 6027 } else if (to() == kUnboxedMint) { |
| 5618 UNREACHABLE(); | 6028 ASSERT((from() == kUnboxedInt32) || (from() == kUnboxedUint32)); |
| 6029 summary->set_in(0, Location::RequiresRegister()); | |
| 6030 summary->set_out(0, Location::SameAsFirstInput()); | |
| 5619 } else { | 6031 } else { |
| 5620 ASSERT((to() == kUnboxedUint32) || (to() == kUnboxedInt32)); | 6032 ASSERT((to() == kUnboxedUint32) || (to() == kUnboxedInt32)); |
| 5621 ASSERT((from() == kUnboxedUint32) || (from() == kUnboxedInt32)); | 6033 ASSERT((from() == kUnboxedUint32) || (from() == kUnboxedInt32)); |
| 5622 summary->set_in(0, Location::RequiresRegister()); | 6034 summary->set_in(0, Location::RequiresRegister()); |
| 5623 summary->set_out(0, Location::SameAsFirstInput()); | 6035 summary->set_out(0, Location::SameAsFirstInput()); |
| 5624 } | 6036 } |
| 5625 return summary; | 6037 return summary; |
| 5626 } | 6038 } |
| 5627 | 6039 |
| 5628 | 6040 |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 5640 const Register value = locs()->in(0).reg(); | 6052 const Register value = locs()->in(0).reg(); |
| 5641 const Register out = locs()->out(0).reg(); | 6053 const Register out = locs()->out(0).reg(); |
| 5642 __ movsxd(out, value); | 6054 __ movsxd(out, value); |
| 5643 if (CanDeoptimize()) { | 6055 if (CanDeoptimize()) { |
| 5644 Label* deopt = | 6056 Label* deopt = |
| 5645 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnboxInteger); | 6057 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnboxInteger); |
| 5646 __ testl(out, out); | 6058 __ testl(out, out); |
| 5647 __ j(NEGATIVE, deopt); | 6059 __ j(NEGATIVE, deopt); |
| 5648 } | 6060 } |
| 5649 } else if (from() == kUnboxedMint) { | 6061 } else if (from() == kUnboxedMint) { |
| 5650 UNREACHABLE(); | 6062 ASSERT((to() == kUnboxedUint32) || (to() == kUnboxedInt32)); |
| 6063 const Register value = locs()->in(0).reg(); | |
| 6064 const Register out = locs()->out(0).reg(); | |
| 6065 if (!CanDeoptimize()) { | |
| 6066 // Copy low. | |
| 6067 __ movl(out, value); | |
| 6068 } else { | |
| 6069 Label* deopt = | |
| 6070 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnboxInteger); | |
| 6071 // Sign extend. | |
| 6072 __ movsxd(out, out); | |
|
Vyacheslav Egorov (Google)
2014/10/07 12:03:50
__ movsxd(out, value)
Cutch
2014/10/21 17:42:11
Done.
| |
| 6073 // Compare with original value. | |
| 6074 __ cmpq(out, value); | |
| 6075 // Value cannot be held in Int32, deopt. | |
| 6076 __ j(NOT_EQUAL, deopt); | |
| 6077 } | |
| 5651 } else if (to() == kUnboxedMint) { | 6078 } else if (to() == kUnboxedMint) { |
| 5652 ASSERT((from() == kUnboxedUint32) || (from() == kUnboxedInt32)); | 6079 ASSERT((from() == kUnboxedUint32) || (from() == kUnboxedInt32)); |
| 5653 UNREACHABLE(); | 6080 const Register value = locs()->in(0).reg(); |
| 6081 const Register out = locs()->out(0).reg(); | |
| 6082 if (from() == kUnboxedUint32) { | |
| 6083 // Zero extend. | |
| 6084 __ movl(out, value); | |
| 6085 } else { | |
| 6086 // Sign extend. | |
| 6087 ASSERT(from() == kUnboxedInt32); | |
| 6088 __ movsxd(out, value); | |
| 6089 } | |
| 5654 } else { | 6090 } else { |
| 5655 UNREACHABLE(); | 6091 UNREACHABLE(); |
| 5656 } | 6092 } |
| 5657 } | 6093 } |
| 5658 | 6094 |
| 5659 | 6095 |
| 5660 LocationSummary* ThrowInstr::MakeLocationSummary(Isolate* isolate, | 6096 LocationSummary* ThrowInstr::MakeLocationSummary(Isolate* isolate, |
| 5661 bool opt) const { | 6097 bool opt) const { |
| 5662 return new(isolate) LocationSummary(isolate, 0, 0, LocationSummary::kCall); | 6098 return new(isolate) LocationSummary(isolate, 0, 0, LocationSummary::kCall); |
| 5663 } | 6099 } |
| (...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5927 __ movq(R10, Immediate(kInvalidObjectPointer)); | 6363 __ movq(R10, Immediate(kInvalidObjectPointer)); |
| 5928 __ movq(RBX, Immediate(kInvalidObjectPointer)); | 6364 __ movq(RBX, Immediate(kInvalidObjectPointer)); |
| 5929 #endif | 6365 #endif |
| 5930 } | 6366 } |
| 5931 | 6367 |
| 5932 } // namespace dart | 6368 } // namespace dart |
| 5933 | 6369 |
| 5934 #undef __ | 6370 #undef __ |
| 5935 | 6371 |
| 5936 #endif // defined TARGET_ARCH_X64 | 6372 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |