| 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 EmitInt64ComparisonOp(FlowGraphCompiler* compiler, |
| 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 EmitInt64ComparisonOp(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 EmitInt64ComparisonOp(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 return kTagged; | 990 return kTagged; |
| 972 case kTypedDataInt32ArrayCid: | 991 case kTypedDataInt32ArrayCid: |
| 973 return kUnboxedInt32; | 992 return kUnboxedInt32; |
| 974 case kTypedDataUint32ArrayCid: | 993 case kTypedDataUint32ArrayCid: |
| 975 return kUnboxedUint32; | 994 return kUnboxedUint32; |
| 995 case kTypedDataInt64ArrayCid: |
| 996 return kUnboxedMint; |
| 976 case kTypedDataFloat32ArrayCid: | 997 case kTypedDataFloat32ArrayCid: |
| 977 case kTypedDataFloat64ArrayCid: | 998 case kTypedDataFloat64ArrayCid: |
| 978 return kUnboxedDouble; | 999 return kUnboxedDouble; |
| 979 case kTypedDataInt32x4ArrayCid: | 1000 case kTypedDataInt32x4ArrayCid: |
| 980 return kUnboxedInt32x4; | 1001 return kUnboxedInt32x4; |
| 981 case kTypedDataFloat32x4ArrayCid: | 1002 case kTypedDataFloat32x4ArrayCid: |
| 982 return kUnboxedFloat32x4; | 1003 return kUnboxedFloat32x4; |
| 983 case kTypedDataFloat64x2ArrayCid: | 1004 case kTypedDataFloat64x2ArrayCid: |
| 984 return kUnboxedFloat64x2; | 1005 return kUnboxedFloat64x2; |
| 985 default: | 1006 default: |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1068 case kTypedDataUint32ArrayCid: | 1089 case kTypedDataUint32ArrayCid: |
| 1069 ASSERT(representation() == kUnboxedUint32); | 1090 ASSERT(representation() == kUnboxedUint32); |
| 1070 __ movl(result, element_address); | 1091 __ movl(result, element_address); |
| 1071 break; | 1092 break; |
| 1072 default: | 1093 default: |
| 1073 UNREACHABLE(); | 1094 UNREACHABLE(); |
| 1074 } | 1095 } |
| 1075 return; | 1096 return; |
| 1076 } | 1097 } |
| 1077 | 1098 |
| 1099 if (representation() == kUnboxedMint) { |
| 1100 ASSERT(class_id() == kTypedDataInt64ArrayCid); |
| 1101 if ((index_scale() == 1) && index.IsRegister()) { |
| 1102 __ SmiUntag(index.reg()); |
| 1103 } |
| 1104 Register result = locs()->out(0).reg(); |
| 1105 __ movq(result, element_address); |
| 1106 return; |
| 1107 } |
| 1108 |
| 1078 ASSERT(representation() == kTagged); | 1109 ASSERT(representation() == kTagged); |
| 1079 | 1110 |
| 1080 if ((index_scale() == 1) && index.IsRegister()) { | 1111 if ((index_scale() == 1) && index.IsRegister()) { |
| 1081 __ SmiUntag(index.reg()); | 1112 __ SmiUntag(index.reg()); |
| 1082 } | 1113 } |
| 1083 Register result = locs()->out(0).reg(); | 1114 Register result = locs()->out(0).reg(); |
| 1084 switch (class_id()) { | 1115 switch (class_id()) { |
| 1085 case kTypedDataInt8ArrayCid: | 1116 case kTypedDataInt8ArrayCid: |
| 1086 __ movsxb(result, element_address); | 1117 __ movsxb(result, element_address); |
| 1087 __ SmiTag(result); | 1118 __ SmiTag(result); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1124 case kExternalTypedDataUint8ArrayCid: | 1155 case kExternalTypedDataUint8ArrayCid: |
| 1125 case kTypedDataUint8ClampedArrayCid: | 1156 case kTypedDataUint8ClampedArrayCid: |
| 1126 case kExternalTypedDataUint8ClampedArrayCid: | 1157 case kExternalTypedDataUint8ClampedArrayCid: |
| 1127 case kTypedDataInt16ArrayCid: | 1158 case kTypedDataInt16ArrayCid: |
| 1128 case kTypedDataUint16ArrayCid: | 1159 case kTypedDataUint16ArrayCid: |
| 1129 return kTagged; | 1160 return kTagged; |
| 1130 case kTypedDataInt32ArrayCid: | 1161 case kTypedDataInt32ArrayCid: |
| 1131 return kUnboxedInt32; | 1162 return kUnboxedInt32; |
| 1132 case kTypedDataUint32ArrayCid: | 1163 case kTypedDataUint32ArrayCid: |
| 1133 return kUnboxedUint32; | 1164 return kUnboxedUint32; |
| 1165 case kTypedDataInt64ArrayCid: |
| 1166 return kUnboxedMint; |
| 1134 case kTypedDataFloat32ArrayCid: | 1167 case kTypedDataFloat32ArrayCid: |
| 1135 case kTypedDataFloat64ArrayCid: | 1168 case kTypedDataFloat64ArrayCid: |
| 1136 return kUnboxedDouble; | 1169 return kUnboxedDouble; |
| 1137 case kTypedDataFloat32x4ArrayCid: | 1170 case kTypedDataFloat32x4ArrayCid: |
| 1138 return kUnboxedFloat32x4; | 1171 return kUnboxedFloat32x4; |
| 1139 case kTypedDataInt32x4ArrayCid: | 1172 case kTypedDataInt32x4ArrayCid: |
| 1140 return kUnboxedInt32x4; | 1173 return kUnboxedInt32x4; |
| 1141 case kTypedDataFloat64x2ArrayCid: | 1174 case kTypedDataFloat64x2ArrayCid: |
| 1142 return kUnboxedFloat64x2; | 1175 return kUnboxedFloat64x2; |
| 1143 default: | 1176 default: |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1181 // RBX, RCX, RDX) instead of using a fixed register. | 1214 // RBX, RCX, RDX) instead of using a fixed register. |
| 1182 locs->set_in(2, Location::FixedRegisterOrSmiConstant(value(), RAX)); | 1215 locs->set_in(2, Location::FixedRegisterOrSmiConstant(value(), RAX)); |
| 1183 break; | 1216 break; |
| 1184 case kTypedDataInt16ArrayCid: | 1217 case kTypedDataInt16ArrayCid: |
| 1185 case kTypedDataUint16ArrayCid: | 1218 case kTypedDataUint16ArrayCid: |
| 1186 case kTypedDataInt32ArrayCid: | 1219 case kTypedDataInt32ArrayCid: |
| 1187 case kTypedDataUint32ArrayCid: | 1220 case kTypedDataUint32ArrayCid: |
| 1188 // Writable register because the value must be untagged before storing. | 1221 // Writable register because the value must be untagged before storing. |
| 1189 locs->set_in(2, Location::WritableRegister()); | 1222 locs->set_in(2, Location::WritableRegister()); |
| 1190 break; | 1223 break; |
| 1224 case kTypedDataInt64ArrayCid: |
| 1225 locs->set_in(2, Location::RequiresRegister()); |
| 1226 break; |
| 1191 case kTypedDataFloat32ArrayCid: | 1227 case kTypedDataFloat32ArrayCid: |
| 1192 case kTypedDataFloat64ArrayCid: | 1228 case kTypedDataFloat64ArrayCid: |
| 1193 // TODO(srdjan): Support Float64 constants. | 1229 // TODO(srdjan): Support Float64 constants. |
| 1194 locs->set_in(2, Location::RequiresFpuRegister()); | 1230 locs->set_in(2, Location::RequiresFpuRegister()); |
| 1195 break; | 1231 break; |
| 1196 case kTypedDataInt32x4ArrayCid: | 1232 case kTypedDataInt32x4ArrayCid: |
| 1197 case kTypedDataFloat64x2ArrayCid: | 1233 case kTypedDataFloat64x2ArrayCid: |
| 1198 case kTypedDataFloat32x4ArrayCid: | 1234 case kTypedDataFloat32x4ArrayCid: |
| 1199 locs->set_in(2, Location::RequiresFpuRegister()); | 1235 locs->set_in(2, Location::RequiresFpuRegister()); |
| 1200 break; | 1236 break; |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1284 __ SmiUntag(value); | 1320 __ SmiUntag(value); |
| 1285 __ movw(element_address, value); | 1321 __ movw(element_address, value); |
| 1286 break; | 1322 break; |
| 1287 } | 1323 } |
| 1288 case kTypedDataInt32ArrayCid: | 1324 case kTypedDataInt32ArrayCid: |
| 1289 case kTypedDataUint32ArrayCid: { | 1325 case kTypedDataUint32ArrayCid: { |
| 1290 Register value = locs()->in(2).reg(); | 1326 Register value = locs()->in(2).reg(); |
| 1291 __ movl(element_address, value); | 1327 __ movl(element_address, value); |
| 1292 break; | 1328 break; |
| 1293 } | 1329 } |
| 1330 case kTypedDataInt64ArrayCid: { |
| 1331 Register value = locs()->in(2).reg(); |
| 1332 __ movq(element_address, value); |
| 1333 break; |
| 1334 } |
| 1294 case kTypedDataFloat32ArrayCid: | 1335 case kTypedDataFloat32ArrayCid: |
| 1295 __ movss(element_address, locs()->in(2).fpu_reg()); | 1336 __ movss(element_address, locs()->in(2).fpu_reg()); |
| 1296 break; | 1337 break; |
| 1297 case kTypedDataFloat64ArrayCid: | 1338 case kTypedDataFloat64ArrayCid: |
| 1298 __ movsd(element_address, locs()->in(2).fpu_reg()); | 1339 __ movsd(element_address, locs()->in(2).fpu_reg()); |
| 1299 break; | 1340 break; |
| 1300 case kTypedDataInt32x4ArrayCid: | 1341 case kTypedDataInt32x4ArrayCid: |
| 1301 case kTypedDataFloat64x2ArrayCid: | 1342 case kTypedDataFloat64x2ArrayCid: |
| 1302 case kTypedDataFloat32x4ArrayCid: | 1343 case kTypedDataFloat32x4ArrayCid: |
| 1303 __ movups(element_address, locs()->in(2).fpu_reg()); | 1344 __ movups(element_address, locs()->in(2).fpu_reg()); |
| (...skipping 4181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5485 Register length = length_loc.reg(); | 5526 Register length = length_loc.reg(); |
| 5486 Register index = index_loc.reg(); | 5527 Register index = index_loc.reg(); |
| 5487 __ cmpq(index, length); | 5528 __ cmpq(index, length); |
| 5488 __ j(ABOVE_EQUAL, deopt); | 5529 __ j(ABOVE_EQUAL, deopt); |
| 5489 } | 5530 } |
| 5490 } | 5531 } |
| 5491 | 5532 |
| 5492 | 5533 |
| 5493 LocationSummary* UnboxIntegerInstr::MakeLocationSummary(Isolate* isolate, | 5534 LocationSummary* UnboxIntegerInstr::MakeLocationSummary(Isolate* isolate, |
| 5494 bool opt) const { | 5535 bool opt) const { |
| 5495 UNIMPLEMENTED(); | 5536 const intptr_t kNumInputs = 1; |
| 5496 return NULL; | 5537 const intptr_t kNumTemps = 0; |
| 5538 LocationSummary* locs = new(isolate) LocationSummary( |
| 5539 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5540 locs->set_in(0, Location::RequiresRegister()); |
| 5541 locs->set_out(0, Location::SameAsFirstInput()); |
| 5542 return locs; |
| 5497 } | 5543 } |
| 5498 | 5544 |
| 5499 | 5545 |
| 5500 void UnboxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5546 void UnboxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5501 UNIMPLEMENTED(); | 5547 const intptr_t value_cid = value()->Type()->ToCid(); |
| 5548 const Register value = locs()->in(0).reg(); |
| 5549 const Register result = locs()->out(0).reg(); |
| 5550 ASSERT(value == result); |
| 5551 |
| 5552 if (value_cid == kMintCid) { |
| 5553 __ movq(result, FieldAddress(value, Mint::value_offset())); |
| 5554 } else if (value_cid == kSmiCid) { |
| 5555 __ SmiUntag(result); |
| 5556 } else { |
| 5557 Label* deopt = compiler->AddDeoptStub(deopt_id_, |
| 5558 ICData::kDeoptUnboxInteger); |
| 5559 Label done; |
| 5560 __ SmiUntagOrCheckClass(value, kMintCid, &done); |
| 5561 __ j(NOT_EQUAL, deopt); |
| 5562 // Undo untagging by multiplying value with 2. |
| 5563 __ movq(result, Address(value, TIMES_2, Mint::value_offset())); |
| 5564 __ Bind(&done); |
| 5565 } |
| 5502 } | 5566 } |
| 5503 | 5567 |
| 5504 | 5568 |
| 5505 LocationSummary* BoxIntegerInstr::MakeLocationSummary(Isolate* isolate, | 5569 LocationSummary* BoxIntegerInstr::MakeLocationSummary(Isolate* isolate, |
| 5506 bool opt) const { | 5570 bool opt) const { |
| 5507 UNIMPLEMENTED(); | 5571 const intptr_t kNumInputs = 1; |
| 5508 return NULL; | 5572 const intptr_t kNumTemps = 0; |
| 5573 LocationSummary* summary = new(isolate) LocationSummary( |
| 5574 isolate, kNumInputs, kNumTemps, is_smi() |
| 5575 ? LocationSummary::kNoCall |
| 5576 : LocationSummary::kCallOnSlowPath); |
| 5577 summary->set_in(0, Location::RequiresRegister()); |
| 5578 summary->set_out(0, Location::RequiresRegister()); |
| 5579 return summary; |
| 5509 } | 5580 } |
| 5510 | 5581 |
| 5511 | 5582 |
| 5512 void BoxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5583 void BoxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5513 UNIMPLEMENTED(); | 5584 const Register out = locs()->out(0).reg(); |
| 5585 const Register value = locs()->in(0).reg(); |
| 5586 |
| 5587 if (is_smi()) { |
| 5588 __ movq(out, value); |
| 5589 __ SmiTag(out); |
| 5590 return; |
| 5591 } |
| 5592 |
| 5593 Label is_smi; |
| 5594 Label done; |
| 5595 __ movq(out, value); |
| 5596 __ SmiTag(out); // shlq sets OF := SF ^ CF on 1 bit shifts |
| 5597 __ j(NO_OVERFLOW, &done); |
| 5598 BoxAllocationSlowPath::Allocate( |
| 5599 compiler, this, compiler->mint_class(), out); |
| 5600 __ movq(FieldAddress(out, Mint::value_offset()), value); |
| 5601 __ Bind(&done); |
| 5602 } |
| 5603 |
| 5604 |
| 5605 template<typename OperandType> |
| 5606 static void EmitInt64Arithmetic(FlowGraphCompiler* compiler, |
| 5607 Token::Kind op_kind, |
| 5608 Register left, |
| 5609 const OperandType& right, |
| 5610 Label* deopt) { |
| 5611 switch (op_kind) { |
| 5612 case Token::kADD: |
| 5613 __ addq(left, right); |
| 5614 break; |
| 5615 case Token::kSUB: |
| 5616 __ subq(left, right); |
| 5617 break; |
| 5618 case Token::kBIT_AND: |
| 5619 __ andq(left, right); |
| 5620 break; |
| 5621 case Token::kBIT_OR: |
| 5622 __ orq(left, right); |
| 5623 break; |
| 5624 case Token::kBIT_XOR: |
| 5625 __ xorq(left, right); |
| 5626 break; |
| 5627 case Token::kMUL: |
| 5628 __ imulq(left, right); |
| 5629 break; |
| 5630 default: |
| 5631 UNREACHABLE(); |
| 5632 } |
| 5633 if (deopt != NULL) __ j(OVERFLOW, deopt); |
| 5514 } | 5634 } |
| 5515 | 5635 |
| 5516 | 5636 |
| 5517 LocationSummary* BinaryMintOpInstr::MakeLocationSummary(Isolate* isolate, | 5637 LocationSummary* BinaryMintOpInstr::MakeLocationSummary(Isolate* isolate, |
| 5518 bool opt) const { | 5638 bool opt) const { |
| 5519 UNIMPLEMENTED(); | 5639 const intptr_t kNumInputs = 2; |
| 5520 return NULL; | 5640 const intptr_t kNumTemps = 0; |
| 5641 LocationSummary* summary = new(isolate) LocationSummary( |
| 5642 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5643 summary->set_in(0, Location::RequiresRegister()); |
| 5644 summary->set_in(1, Location::RequiresRegister()); |
| 5645 summary->set_out(0, Location::SameAsFirstInput()); |
| 5646 return summary; |
| 5521 } | 5647 } |
| 5522 | 5648 |
| 5523 | 5649 |
| 5524 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5650 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5525 UNIMPLEMENTED(); | 5651 const Register left = locs()->in(0).reg(); |
| 5652 const Register right = locs()->in(1).reg(); |
| 5653 const Register out = locs()->out(0).reg(); |
| 5654 |
| 5655 ASSERT(out == left); |
| 5656 |
| 5657 Label* deopt = NULL; |
| 5658 if (CanDeoptimize()) { |
| 5659 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp); |
| 5660 } |
| 5661 |
| 5662 EmitInt64Arithmetic(compiler, op_kind(), left, right, deopt); |
| 5663 |
| 5664 if (FLAG_throw_on_javascript_int_overflow) { |
| 5665 EmitJavascriptOverflowCheck(compiler, range(), deopt, out); |
| 5666 } |
| 5526 } | 5667 } |
| 5527 | 5668 |
| 5528 | 5669 |
| 5529 LocationSummary* UnaryMintOpInstr::MakeLocationSummary(Isolate* isolate, | 5670 LocationSummary* UnaryMintOpInstr::MakeLocationSummary(Isolate* isolate, |
| 5530 bool opt) const { | 5671 bool opt) const { |
| 5531 UNIMPLEMENTED(); | 5672 const intptr_t kNumInputs = 1; |
| 5532 return NULL; | 5673 const intptr_t kNumTemps = 0; |
| 5674 LocationSummary* summary = new(isolate) LocationSummary( |
| 5675 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5676 summary->set_in(0, Location::RequiresRegister()); |
| 5677 summary->set_out(0, Location::SameAsFirstInput()); |
| 5678 return summary; |
| 5533 } | 5679 } |
| 5534 | 5680 |
| 5535 | 5681 |
| 5536 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5682 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5537 UNIMPLEMENTED(); | 5683 ASSERT(op_kind() == Token::kBIT_NOT); |
| 5538 } | 5684 const Register left = locs()->in(0).reg(); |
| 5539 | 5685 const Register out = locs()->out(0).reg(); |
| 5686 ASSERT(out == left); |
| 5687 |
| 5688 Label* deopt = NULL; |
| 5689 if (FLAG_throw_on_javascript_int_overflow) { |
| 5690 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryMintOp); |
| 5691 } |
| 5692 |
| 5693 __ notq(left); |
| 5694 |
| 5695 if (FLAG_throw_on_javascript_int_overflow) { |
| 5696 EmitJavascriptOverflowCheck(compiler, range(), deopt, out); |
| 5697 } |
| 5698 } |
| 5699 |
| 5700 |
| 5701 static const intptr_t kMintShiftCountLimit = 63; |
| 5540 | 5702 |
| 5541 bool ShiftMintOpInstr::has_shift_count_check() const { | 5703 bool ShiftMintOpInstr::has_shift_count_check() const { |
| 5542 UNREACHABLE(); | 5704 return !RangeUtils::IsWithin( |
| 5543 return false; | 5705 right()->definition()->range(), 0, kMintShiftCountLimit); |
| 5544 } | 5706 } |
| 5545 | 5707 |
| 5546 | 5708 |
| 5547 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(Isolate* isolate, | 5709 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(Isolate* isolate, |
| 5548 bool opt) const { | 5710 bool opt) const { |
| 5549 UNIMPLEMENTED(); | 5711 const intptr_t kNumInputs = 2; |
| 5550 return NULL; | 5712 const intptr_t kNumTemps = can_overflow() ? 1 : 0; |
| 5713 LocationSummary* summary = new(isolate) LocationSummary( |
| 5714 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5715 summary->set_in(0, Location::RequiresRegister()); |
| 5716 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), RCX)); |
| 5717 if (kNumTemps > 0) { |
| 5718 summary->set_temp(0, Location::RequiresRegister()); |
| 5719 } |
| 5720 summary->set_out(0, Location::SameAsFirstInput()); |
| 5721 return summary; |
| 5551 } | 5722 } |
| 5552 | 5723 |
| 5553 | 5724 |
| 5554 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5725 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5555 UNIMPLEMENTED(); | 5726 const Register left = locs()->in(0).reg(); |
| 5556 } | 5727 const Register out = locs()->out(0).reg(); |
| 5557 | 5728 ASSERT(left == out); |
| 5558 | 5729 |
| 5730 Label* deopt = NULL; |
| 5731 if (CanDeoptimize()) { |
| 5732 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptShiftMintOp); |
| 5733 } |
| 5734 if (locs()->in(1).IsConstant()) { |
| 5735 // Code for a constant shift amount. |
| 5736 ASSERT(locs()->in(1).constant().IsSmi()); |
| 5737 const int64_t shift = |
| 5738 reinterpret_cast<int64_t>(locs()->in(1).constant().raw()) >> 1; |
| 5739 switch (op_kind()) { |
| 5740 case Token::kSHR: |
| 5741 __ sarq(left, Immediate(shift)); |
| 5742 break; |
| 5743 case Token::kSHL: { |
| 5744 if (can_overflow()) { |
| 5745 // Check for overflow. |
| 5746 Register temp = locs()->temp(0).reg(); |
| 5747 __ movq(temp, left); |
| 5748 __ shlq(left, Immediate(shift)); |
| 5749 __ sarq(left, Immediate(shift)); |
| 5750 __ cmpq(left, temp); |
| 5751 __ j(NOT_EQUAL, deopt); // Overflow. |
| 5752 } |
| 5753 // Shift for result now we know there is no overflow. |
| 5754 __ shlq(left, Immediate(shift)); |
| 5755 break; |
| 5756 } |
| 5757 default: |
| 5758 UNREACHABLE(); |
| 5759 } |
| 5760 } else { |
| 5761 // Code for a variable shift amount. |
| 5762 // Deoptimize if shift count is > 63. |
| 5763 // sarl operation masks the count to 5 bits and |
| 5764 // shrd is undefined with count > operand size (32) |
| 5765 __ SmiUntag(RCX); |
| 5766 if (has_shift_count_check()) { |
| 5767 __ cmpq(RCX, Immediate(kMintShiftCountLimit)); |
| 5768 __ j(ABOVE, deopt); |
| 5769 } |
| 5770 Label done, large_shift; |
| 5771 switch (op_kind()) { |
| 5772 case Token::kSHR: { |
| 5773 __ sarq(left, RCX); |
| 5774 break; |
| 5775 } |
| 5776 case Token::kSHL: { |
| 5777 if (can_overflow()) { |
| 5778 // Check for overflow. |
| 5779 Register temp = locs()->temp(0).reg(); |
| 5780 __ movq(temp, left); |
| 5781 __ shlq(left, RCX); |
| 5782 __ sarq(left, RCX); |
| 5783 __ cmpq(left, temp); |
| 5784 __ j(NOT_EQUAL, deopt); // Overflow. |
| 5785 } |
| 5786 // Shift for result now we know there is no overflow. |
| 5787 __ shlq(left, RCX); |
| 5788 break; |
| 5789 } |
| 5790 default: |
| 5791 UNREACHABLE(); |
| 5792 } |
| 5793 } |
| 5794 if (FLAG_throw_on_javascript_int_overflow) { |
| 5795 EmitJavascriptOverflowCheck(compiler, range(), deopt, out); |
| 5796 } |
| 5797 } |
| 5798 |
| 5799 |
| 5559 CompileType BinaryUint32OpInstr::ComputeType() const { | 5800 CompileType BinaryUint32OpInstr::ComputeType() const { |
| 5560 return CompileType::FromCid(kSmiCid); | 5801 return CompileType::FromCid(kSmiCid); |
| 5561 } | 5802 } |
| 5562 | 5803 |
| 5563 | 5804 |
| 5564 CompileType ShiftUint32OpInstr::ComputeType() const { | 5805 CompileType ShiftUint32OpInstr::ComputeType() const { |
| 5565 return CompileType::FromCid(kSmiCid); | 5806 return CompileType::FromCid(kSmiCid); |
| 5566 } | 5807 } |
| 5567 | 5808 |
| 5568 | 5809 |
| 5569 CompileType UnaryUint32OpInstr::ComputeType() const { | 5810 CompileType UnaryUint32OpInstr::ComputeType() const { |
| 5570 return CompileType::FromCid(kSmiCid); | 5811 return CompileType::FromCid(kSmiCid); |
| 5571 } | 5812 } |
| 5572 | 5813 |
| 5573 | 5814 |
| 5574 DEFINE_UNIMPLEMENTED_INSTRUCTION(BinaryUint32OpInstr) | 5815 LocationSummary* BinaryUint32OpInstr::MakeLocationSummary(Isolate* isolate, |
| 5575 DEFINE_UNIMPLEMENTED_INSTRUCTION(ShiftUint32OpInstr) | 5816 bool opt) const { |
| 5576 DEFINE_UNIMPLEMENTED_INSTRUCTION(UnaryUint32OpInstr) | 5817 const intptr_t kNumInputs = 2; |
| 5818 const intptr_t kNumTemps = (op_kind() == Token::kMUL) ? 1 : 0; |
| 5819 LocationSummary* summary = new(isolate) LocationSummary( |
| 5820 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5821 summary->set_in(0, Location::RequiresRegister()); |
| 5822 summary->set_in(1, Location::RequiresRegister()); |
| 5823 summary->set_out(0, Location::SameAsFirstInput()); |
| 5824 return summary; |
| 5825 } |
| 5826 |
| 5827 |
| 5828 template<typename OperandType> |
| 5829 static void EmitIntegerArithmetic(FlowGraphCompiler* compiler, |
| 5830 Token::Kind op_kind, |
| 5831 Register left, |
| 5832 const OperandType& right, |
| 5833 Label* deopt) { |
| 5834 switch (op_kind) { |
| 5835 case Token::kADD: |
| 5836 __ addl(left, right); |
| 5837 break; |
| 5838 case Token::kSUB: |
| 5839 __ subl(left, right); |
| 5840 break; |
| 5841 case Token::kBIT_AND: |
| 5842 __ andl(left, right); |
| 5843 break; |
| 5844 case Token::kBIT_OR: |
| 5845 __ orl(left, right); |
| 5846 break; |
| 5847 case Token::kBIT_XOR: |
| 5848 __ xorl(left, right); |
| 5849 break; |
| 5850 case Token::kMUL: |
| 5851 __ imull(left, right); |
| 5852 break; |
| 5853 default: |
| 5854 UNREACHABLE(); |
| 5855 } |
| 5856 if (deopt != NULL) __ j(OVERFLOW, deopt); |
| 5857 } |
| 5858 |
| 5859 |
| 5860 void BinaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5861 Register left = locs()->in(0).reg(); |
| 5862 Register right = locs()->in(1).reg(); |
| 5863 Register out = locs()->out(0).reg(); |
| 5864 ASSERT(out == left); |
| 5865 switch (op_kind()) { |
| 5866 case Token::kBIT_AND: |
| 5867 case Token::kBIT_OR: |
| 5868 case Token::kBIT_XOR: |
| 5869 case Token::kADD: |
| 5870 case Token::kSUB: |
| 5871 case Token::kMUL: |
| 5872 EmitIntegerArithmetic(compiler, op_kind(), left, right, NULL); |
| 5873 return; |
| 5874 default: |
| 5875 UNREACHABLE(); |
| 5876 } |
| 5877 } |
| 5878 |
| 5879 |
| 5880 LocationSummary* ShiftUint32OpInstr::MakeLocationSummary(Isolate* isolate, |
| 5881 bool opt) const { |
| 5882 const intptr_t kNumInputs = 2; |
| 5883 const intptr_t kNumTemps = 0; |
| 5884 LocationSummary* summary = new(isolate) LocationSummary( |
| 5885 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5886 summary->set_in(0, Location::RequiresRegister()); |
| 5887 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), RCX)); |
| 5888 summary->set_out(0, Location::SameAsFirstInput()); |
| 5889 return summary; |
| 5890 } |
| 5891 |
| 5892 |
| 5893 void ShiftUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5894 const intptr_t kShifterLimit = 31; |
| 5895 |
| 5896 Register left = locs()->in(0).reg(); |
| 5897 Register out = locs()->out(0).reg(); |
| 5898 ASSERT(left == out); |
| 5899 |
| 5900 |
| 5901 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptShiftMintOp); |
| 5902 |
| 5903 if (locs()->in(1).IsConstant()) { |
| 5904 // Shifter is constant. |
| 5905 |
| 5906 const Object& constant = locs()->in(1).constant(); |
| 5907 ASSERT(constant.IsSmi()); |
| 5908 const intptr_t shift_value = Smi::Cast(constant).Value(); |
| 5909 |
| 5910 // Do the shift: (shift_value > 0) && (shift_value <= kShifterLimit). |
| 5911 switch (op_kind()) { |
| 5912 case Token::kSHR: |
| 5913 __ shrl(left, Immediate(shift_value)); |
| 5914 break; |
| 5915 case Token::kSHL: |
| 5916 __ shll(left, Immediate(shift_value)); |
| 5917 break; |
| 5918 default: |
| 5919 UNREACHABLE(); |
| 5920 } |
| 5921 return; |
| 5922 } |
| 5923 |
| 5924 // Non constant shift value. |
| 5925 |
| 5926 Register shifter = locs()->in(1).reg(); |
| 5927 ASSERT(shifter == RCX); |
| 5928 |
| 5929 Label done; |
| 5930 Label zero; |
| 5931 |
| 5932 // TODO(johnmccutchan): Use range information to avoid these checks. |
| 5933 __ SmiUntag(shifter); |
| 5934 __ cmpq(shifter, Immediate(0)); |
| 5935 // If shift value is < 0, deoptimize. |
| 5936 __ j(NEGATIVE, deopt); |
| 5937 __ cmpq(shifter, Immediate(kShifterLimit)); |
| 5938 // If shift value is >= 32, return zero. |
| 5939 __ j(ABOVE, &zero); |
| 5940 |
| 5941 // Do the shift. |
| 5942 switch (op_kind()) { |
| 5943 case Token::kSHR: |
| 5944 __ shrl(left, shifter); |
| 5945 __ jmp(&done); |
| 5946 break; |
| 5947 case Token::kSHL: |
| 5948 __ shll(left, shifter); |
| 5949 __ jmp(&done); |
| 5950 break; |
| 5951 default: |
| 5952 UNREACHABLE(); |
| 5953 } |
| 5954 |
| 5955 __ Bind(&zero); |
| 5956 // Shift was greater than 31 bits, just return zero. |
| 5957 __ xorq(left, left); |
| 5958 |
| 5959 // Exit path. |
| 5960 __ Bind(&done); |
| 5961 } |
| 5962 |
| 5963 |
| 5964 LocationSummary* UnaryUint32OpInstr::MakeLocationSummary(Isolate* isolate, |
| 5965 bool opt) const { |
| 5966 const intptr_t kNumInputs = 1; |
| 5967 const intptr_t kNumTemps = 0; |
| 5968 LocationSummary* summary = new(isolate) LocationSummary( |
| 5969 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5970 summary->set_in(0, Location::RequiresRegister()); |
| 5971 summary->set_out(0, Location::SameAsFirstInput()); |
| 5972 return summary; |
| 5973 } |
| 5974 |
| 5975 |
| 5976 void UnaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5977 Register out = locs()->out(0).reg(); |
| 5978 ASSERT(locs()->in(0).reg() == out); |
| 5979 |
| 5980 ASSERT(op_kind() == Token::kBIT_NOT); |
| 5981 |
| 5982 __ notl(out); |
| 5983 } |
| 5984 |
| 5985 |
| 5577 DEFINE_UNIMPLEMENTED_INSTRUCTION(BinaryInt32OpInstr) | 5986 DEFINE_UNIMPLEMENTED_INSTRUCTION(BinaryInt32OpInstr) |
| 5578 | 5987 |
| 5579 | 5988 |
| 5580 LocationSummary* UnboxIntNInstr::MakeLocationSummary(Isolate* isolate, | 5989 LocationSummary* UnboxIntNInstr::MakeLocationSummary(Isolate* isolate, |
| 5581 bool opt) const { | 5990 bool opt) const { |
| 5582 const intptr_t kNumInputs = 1; | 5991 const intptr_t kNumInputs = 1; |
| 5583 const intptr_t kNumTemps = (!is_truncating() && CanDeoptimize()) ? 1 : 0; | 5992 const intptr_t kNumTemps = (!is_truncating() && CanDeoptimize()) ? 1 : 0; |
| 5584 LocationSummary* summary = new(isolate) LocationSummary( | 5993 LocationSummary* summary = new(isolate) LocationSummary( |
| 5585 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5994 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5586 summary->set_in(0, Location::RequiresRegister()); | 5995 summary->set_in(0, Location::RequiresRegister()); |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5658 } | 6067 } |
| 5659 | 6068 |
| 5660 | 6069 |
| 5661 LocationSummary* UnboxedIntConverterInstr::MakeLocationSummary(Isolate* isolate, | 6070 LocationSummary* UnboxedIntConverterInstr::MakeLocationSummary(Isolate* isolate, |
| 5662 bool opt) const { | 6071 bool opt) const { |
| 5663 const intptr_t kNumInputs = 1; | 6072 const intptr_t kNumInputs = 1; |
| 5664 const intptr_t kNumTemps = 0; | 6073 const intptr_t kNumTemps = 0; |
| 5665 LocationSummary* summary = new(isolate) LocationSummary( | 6074 LocationSummary* summary = new(isolate) LocationSummary( |
| 5666 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6075 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5667 if (from() == kUnboxedMint) { | 6076 if (from() == kUnboxedMint) { |
| 5668 UNREACHABLE(); | 6077 ASSERT((to() == kUnboxedUint32) || (to() == kUnboxedInt32)); |
| 6078 summary->set_in(0, Location::RequiresRegister()); |
| 6079 summary->set_out(0, Location::SameAsFirstInput()); |
| 5669 } else if (to() == kUnboxedMint) { | 6080 } else if (to() == kUnboxedMint) { |
| 5670 UNREACHABLE(); | 6081 ASSERT((from() == kUnboxedInt32) || (from() == kUnboxedUint32)); |
| 6082 summary->set_in(0, Location::RequiresRegister()); |
| 6083 summary->set_out(0, Location::SameAsFirstInput()); |
| 5671 } else { | 6084 } else { |
| 5672 ASSERT((to() == kUnboxedUint32) || (to() == kUnboxedInt32)); | 6085 ASSERT((to() == kUnboxedUint32) || (to() == kUnboxedInt32)); |
| 5673 ASSERT((from() == kUnboxedUint32) || (from() == kUnboxedInt32)); | 6086 ASSERT((from() == kUnboxedUint32) || (from() == kUnboxedInt32)); |
| 5674 summary->set_in(0, Location::RequiresRegister()); | 6087 summary->set_in(0, Location::RequiresRegister()); |
| 5675 summary->set_out(0, Location::SameAsFirstInput()); | 6088 summary->set_out(0, Location::SameAsFirstInput()); |
| 5676 } | 6089 } |
| 5677 return summary; | 6090 return summary; |
| 5678 } | 6091 } |
| 5679 | 6092 |
| 5680 | 6093 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 5692 const Register value = locs()->in(0).reg(); | 6105 const Register value = locs()->in(0).reg(); |
| 5693 const Register out = locs()->out(0).reg(); | 6106 const Register out = locs()->out(0).reg(); |
| 5694 __ movsxd(out, value); | 6107 __ movsxd(out, value); |
| 5695 if (CanDeoptimize()) { | 6108 if (CanDeoptimize()) { |
| 5696 Label* deopt = | 6109 Label* deopt = |
| 5697 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnboxInteger); | 6110 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnboxInteger); |
| 5698 __ testl(out, out); | 6111 __ testl(out, out); |
| 5699 __ j(NEGATIVE, deopt); | 6112 __ j(NEGATIVE, deopt); |
| 5700 } | 6113 } |
| 5701 } else if (from() == kUnboxedMint) { | 6114 } else if (from() == kUnboxedMint) { |
| 5702 UNREACHABLE(); | 6115 ASSERT((to() == kUnboxedUint32) || (to() == kUnboxedInt32)); |
| 6116 const Register value = locs()->in(0).reg(); |
| 6117 const Register out = locs()->out(0).reg(); |
| 6118 if (!CanDeoptimize()) { |
| 6119 // Copy low. |
| 6120 __ movl(out, value); |
| 6121 } else { |
| 6122 Label* deopt = |
| 6123 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnboxInteger); |
| 6124 // Sign extend. |
| 6125 __ movsxd(out, value); |
| 6126 // Compare with original value. |
| 6127 __ cmpq(out, value); |
| 6128 // Value cannot be held in Int32, deopt. |
| 6129 __ j(NOT_EQUAL, deopt); |
| 6130 } |
| 5703 } else if (to() == kUnboxedMint) { | 6131 } else if (to() == kUnboxedMint) { |
| 5704 ASSERT((from() == kUnboxedUint32) || (from() == kUnboxedInt32)); | 6132 ASSERT((from() == kUnboxedUint32) || (from() == kUnboxedInt32)); |
| 5705 UNREACHABLE(); | 6133 const Register value = locs()->in(0).reg(); |
| 6134 const Register out = locs()->out(0).reg(); |
| 6135 if (from() == kUnboxedUint32) { |
| 6136 // Zero extend. |
| 6137 __ movl(out, value); |
| 6138 } else { |
| 6139 // Sign extend. |
| 6140 ASSERT(from() == kUnboxedInt32); |
| 6141 __ movsxd(out, value); |
| 6142 } |
| 5706 } else { | 6143 } else { |
| 5707 UNREACHABLE(); | 6144 UNREACHABLE(); |
| 5708 } | 6145 } |
| 5709 } | 6146 } |
| 5710 | 6147 |
| 5711 | 6148 |
| 5712 LocationSummary* ThrowInstr::MakeLocationSummary(Isolate* isolate, | 6149 LocationSummary* ThrowInstr::MakeLocationSummary(Isolate* isolate, |
| 5713 bool opt) const { | 6150 bool opt) const { |
| 5714 return new(isolate) LocationSummary(isolate, 0, 0, LocationSummary::kCall); | 6151 return new(isolate) LocationSummary(isolate, 0, 0, LocationSummary::kCall); |
| 5715 } | 6152 } |
| (...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5965 __ movq(R10, Immediate(kInvalidObjectPointer)); | 6402 __ movq(R10, Immediate(kInvalidObjectPointer)); |
| 5966 __ movq(RBX, Immediate(kInvalidObjectPointer)); | 6403 __ movq(RBX, Immediate(kInvalidObjectPointer)); |
| 5967 #endif | 6404 #endif |
| 5968 } | 6405 } |
| 5969 | 6406 |
| 5970 } // namespace dart | 6407 } // namespace dart |
| 5971 | 6408 |
| 5972 #undef __ | 6409 #undef __ |
| 5973 | 6410 |
| 5974 #endif // defined TARGET_ARCH_X64 | 6411 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |