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_IA32. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32. |
6 #if defined(TARGET_ARCH_IA32) | 6 #if defined(TARGET_ARCH_IA32) |
7 | 7 |
8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
9 | 9 |
10 #include "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
246 default: | 246 default: |
247 UNREACHABLE(); | 247 UNREACHABLE(); |
248 return OVERFLOW; | 248 return OVERFLOW; |
249 } | 249 } |
250 } | 250 } |
251 | 251 |
252 | 252 |
253 LocationSummary* EqualityCompareInstr::MakeLocationSummary(bool opt) const { | 253 LocationSummary* EqualityCompareInstr::MakeLocationSummary(bool opt) const { |
254 const intptr_t kNumInputs = 2; | 254 const intptr_t kNumInputs = 2; |
255 if (operation_cid() == kMintCid) { | 255 if (operation_cid() == kMintCid) { |
256 const intptr_t kNumTemps = 1; | 256 const intptr_t kNumTemps = 0; |
257 LocationSummary* locs = | 257 LocationSummary* locs = |
258 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 258 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
259 locs->set_in(0, Location::RequiresFpuRegister()); | 259 locs->set_in(0, Location::Pair(Location::RequiresRegister(), |
260 locs->set_in(1, Location::RequiresFpuRegister()); | 260 Location::RequiresRegister())); |
261 locs->set_temp(0, Location::RequiresRegister()); | 261 locs->set_in(1, Location::Pair(Location::RequiresRegister(), |
262 Location::RequiresRegister())); | |
262 locs->set_out(0, Location::RequiresRegister()); | 263 locs->set_out(0, Location::RequiresRegister()); |
263 return locs; | 264 return locs; |
264 } | 265 } |
265 if (operation_cid() == kDoubleCid) { | 266 if (operation_cid() == kDoubleCid) { |
266 const intptr_t kNumTemps = 0; | 267 const intptr_t kNumTemps = 0; |
267 LocationSummary* locs = | 268 LocationSummary* locs = |
268 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 269 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
269 locs->set_in(0, Location::RequiresFpuRegister()); | 270 locs->set_in(0, Location::RequiresFpuRegister()); |
270 locs->set_in(1, Location::RequiresFpuRegister()); | 271 locs->set_in(1, Location::RequiresFpuRegister()); |
271 locs->set_out(0, Location::RequiresRegister()); | 272 locs->set_out(0, Location::RequiresRegister()); |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
385 __ cmpl(left.reg(), right.ToStackSlotAddress()); | 386 __ cmpl(left.reg(), right.ToStackSlotAddress()); |
386 } else { | 387 } else { |
387 __ cmpl(left.reg(), right.reg()); | 388 __ cmpl(left.reg(), right.reg()); |
388 } | 389 } |
389 return true_condition; | 390 return true_condition; |
390 } | 391 } |
391 | 392 |
392 | 393 |
393 static void EmitJavascriptIntOverflowCheck(FlowGraphCompiler* compiler, | 394 static void EmitJavascriptIntOverflowCheck(FlowGraphCompiler* compiler, |
394 Label* overflow, | 395 Label* overflow, |
395 XmmRegister result, | 396 Register result_lo, |
396 Register tmp) { | 397 Register result_hi) { |
397 // Compare upper half. | 398 // Compare upper half. |
398 Label check_lower; | 399 Label check_lower; |
399 __ pextrd(tmp, result, Immediate(1)); | 400 __ cmpl(result_hi, Immediate(0x00200000)); |
400 __ cmpl(tmp, Immediate(0x00200000)); | |
401 __ j(GREATER, overflow); | 401 __ j(GREATER, overflow); |
402 __ j(NOT_EQUAL, &check_lower); | 402 __ j(NOT_EQUAL, &check_lower); |
403 | 403 |
404 __ pextrd(tmp, result, Immediate(0)); | 404 __ cmpl(result_lo, Immediate(0)); |
405 __ cmpl(tmp, Immediate(0)); | |
406 __ j(ABOVE, overflow); | 405 __ j(ABOVE, overflow); |
407 | 406 |
408 __ Bind(&check_lower); | 407 __ Bind(&check_lower); |
409 __ pextrd(tmp, result, Immediate(1)); | 408 __ cmpl(result_hi, Immediate(-0x00200000)); |
410 __ cmpl(tmp, Immediate(-0x00200000)); | |
411 __ j(LESS, overflow); | 409 __ j(LESS, overflow); |
412 // Anything in the lower part would make the number bigger than the lower | 410 // Anything in the lower part would make the number bigger than the lower |
413 // bound, so we are done. | 411 // bound, so we are done. |
414 } | 412 } |
415 | 413 |
416 | 414 |
417 static Condition TokenKindToMintCondition(Token::Kind kind) { | 415 static Condition TokenKindToMintCondition(Token::Kind kind) { |
418 switch (kind) { | 416 switch (kind) { |
419 case Token::kEQ: return EQUAL; | 417 case Token::kEQ: return EQUAL; |
420 case Token::kNE: return NOT_EQUAL; | 418 case Token::kNE: return NOT_EQUAL; |
421 case Token::kLT: return LESS; | 419 case Token::kLT: return LESS; |
422 case Token::kGT: return GREATER; | 420 case Token::kGT: return GREATER; |
423 case Token::kLTE: return LESS_EQUAL; | 421 case Token::kLTE: return LESS_EQUAL; |
424 case Token::kGTE: return GREATER_EQUAL; | 422 case Token::kGTE: return GREATER_EQUAL; |
425 default: | 423 default: |
426 UNREACHABLE(); | 424 UNREACHABLE(); |
427 return OVERFLOW; | 425 return OVERFLOW; |
428 } | 426 } |
429 } | 427 } |
430 | 428 |
431 | 429 |
432 static Condition EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler, | 430 static Condition EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler, |
433 const LocationSummary& locs, | 431 const LocationSummary& locs, |
434 Token::Kind kind, | 432 Token::Kind kind, |
435 BranchLabels labels) { | 433 BranchLabels labels) { |
436 ASSERT(Token::IsEqualityOperator(kind)); | 434 ASSERT(Token::IsEqualityOperator(kind)); |
437 XmmRegister left = locs.in(0).fpu_reg(); | 435 PairLocation* left_pair = locs.in(0).AsPairLocation(); |
438 XmmRegister right = locs.in(1).fpu_reg(); | 436 Register left1 = left_pair->At(0).reg(); |
439 Register temp = locs.temp(0).reg(); | 437 Register left2 = left_pair->At(1).reg(); |
440 __ movaps(XMM0, left); | 438 PairLocation* right_pair = locs.in(1).AsPairLocation(); |
441 __ pcmpeqq(XMM0, right); | 439 Register right1 = right_pair->At(0).reg(); |
442 __ movd(temp, XMM0); | 440 Register right2 = right_pair->At(1).reg(); |
443 | 441 Label done; |
442 // Compare lower. | |
443 __ cmpl(left1, right1); | |
444 __ j(NOT_EQUAL, &done); | |
445 // Lower is equal, compare upper. | |
446 __ cmpl(left2, right2); | |
447 __ Bind(&done); | |
444 Condition true_condition = TokenKindToMintCondition(kind); | 448 Condition true_condition = TokenKindToMintCondition(kind); |
445 __ cmpl(temp, Immediate(-1)); | |
446 return true_condition; | 449 return true_condition; |
447 } | 450 } |
448 | 451 |
449 | 452 |
450 static Condition EmitUnboxedMintComparisonOp(FlowGraphCompiler* compiler, | 453 static Condition EmitUnboxedMintComparisonOp(FlowGraphCompiler* compiler, |
451 const LocationSummary& locs, | 454 const LocationSummary& locs, |
452 Token::Kind kind, | 455 Token::Kind kind, |
453 BranchLabels labels) { | 456 BranchLabels labels) { |
454 XmmRegister left = locs.in(0).fpu_reg(); | 457 PairLocation* left_pair = locs.in(0).AsPairLocation(); |
455 XmmRegister right = locs.in(1).fpu_reg(); | 458 Register left1 = left_pair->At(0).reg(); |
456 Register left_tmp = locs.temp(0).reg(); | 459 Register left2 = left_pair->At(1).reg(); |
457 Register right_tmp = locs.temp(1).reg(); | 460 PairLocation* right_pair = locs.in(1).AsPairLocation(); |
461 Register right1 = right_pair->At(0).reg(); | |
462 Register right2 = right_pair->At(1).reg(); | |
458 | 463 |
459 Condition hi_cond = OVERFLOW, lo_cond = OVERFLOW; | 464 Condition hi_cond = OVERFLOW, lo_cond = OVERFLOW; |
460 switch (kind) { | 465 switch (kind) { |
461 case Token::kLT: | 466 case Token::kLT: |
462 hi_cond = LESS; | 467 hi_cond = LESS; |
463 lo_cond = BELOW; | 468 lo_cond = BELOW; |
464 break; | 469 break; |
465 case Token::kGT: | 470 case Token::kGT: |
466 hi_cond = GREATER; | 471 hi_cond = GREATER; |
467 lo_cond = ABOVE; | 472 lo_cond = ABOVE; |
468 break; | 473 break; |
469 case Token::kLTE: | 474 case Token::kLTE: |
470 hi_cond = LESS; | 475 hi_cond = LESS; |
471 lo_cond = BELOW_EQUAL; | 476 lo_cond = BELOW_EQUAL; |
472 break; | 477 break; |
473 case Token::kGTE: | 478 case Token::kGTE: |
474 hi_cond = GREATER; | 479 hi_cond = GREATER; |
475 lo_cond = ABOVE_EQUAL; | 480 lo_cond = ABOVE_EQUAL; |
476 break; | 481 break; |
477 default: | 482 default: |
478 break; | 483 break; |
479 } | 484 } |
480 ASSERT(hi_cond != OVERFLOW && lo_cond != OVERFLOW); | 485 ASSERT(hi_cond != OVERFLOW && lo_cond != OVERFLOW); |
481 Label is_true, is_false; | 486 Label is_true, is_false; |
482 // Compare upper halves first. | 487 // Compare upper halves first. |
483 __ pextrd(left_tmp, left, Immediate(1)); | 488 __ cmpl(left2, right2); |
484 __ pextrd(right_tmp, right, Immediate(1)); | |
485 __ cmpl(left_tmp, right_tmp); | |
486 __ j(hi_cond, labels.true_label); | 489 __ j(hi_cond, labels.true_label); |
487 __ j(FlipCondition(hi_cond), labels.false_label); | 490 __ j(FlipCondition(hi_cond), labels.false_label); |
488 | 491 |
489 // If upper is equal, compare lower half. | 492 // If upper is equal, compare lower half. |
490 __ pextrd(left_tmp, left, Immediate(0)); | 493 __ cmpl(left1, right1); |
491 __ pextrd(right_tmp, right, Immediate(0)); | |
492 __ cmpl(left_tmp, right_tmp); | |
493 return lo_cond; | 494 return lo_cond; |
494 } | 495 } |
495 | 496 |
496 | 497 |
497 static Condition TokenKindToDoubleCondition(Token::Kind kind) { | 498 static Condition TokenKindToDoubleCondition(Token::Kind kind) { |
498 switch (kind) { | 499 switch (kind) { |
499 case Token::kEQ: return EQUAL; | 500 case Token::kEQ: return EQUAL; |
500 case Token::kNE: return NOT_EQUAL; | 501 case Token::kNE: return NOT_EQUAL; |
501 case Token::kLT: return BELOW; | 502 case Token::kLT: return BELOW; |
502 case Token::kGT: return ABOVE; | 503 case Token::kGT: return ABOVE; |
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
681 __ Bind(&is_true); | 682 __ Bind(&is_true); |
682 __ LoadObject(result_reg, Bool::True()); | 683 __ LoadObject(result_reg, Bool::True()); |
683 __ Bind(&done); | 684 __ Bind(&done); |
684 } | 685 } |
685 | 686 |
686 | 687 |
687 LocationSummary* RelationalOpInstr::MakeLocationSummary(bool opt) const { | 688 LocationSummary* RelationalOpInstr::MakeLocationSummary(bool opt) const { |
688 const intptr_t kNumInputs = 2; | 689 const intptr_t kNumInputs = 2; |
689 const intptr_t kNumTemps = 0; | 690 const intptr_t kNumTemps = 0; |
690 if (operation_cid() == kMintCid) { | 691 if (operation_cid() == kMintCid) { |
691 const intptr_t kNumTemps = 2; | 692 const intptr_t kNumTemps = 0; |
692 LocationSummary* locs = | 693 LocationSummary* locs = |
693 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 694 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
694 locs->set_in(0, Location::RequiresFpuRegister()); | 695 locs->set_in(0, Location::Pair(Location::RequiresRegister(), |
695 locs->set_in(1, Location::RequiresFpuRegister()); | 696 Location::RequiresRegister())); |
696 locs->set_temp(0, Location::RequiresRegister()); | 697 locs->set_in(1, Location::Pair(Location::RequiresRegister(), |
697 locs->set_temp(1, Location::RequiresRegister()); | 698 Location::RequiresRegister())); |
698 locs->set_out(0, Location::RequiresRegister()); | 699 locs->set_out(0, Location::RequiresRegister()); |
699 return locs; | 700 return locs; |
700 } | 701 } |
701 if (operation_cid() == kDoubleCid) { | 702 if (operation_cid() == kDoubleCid) { |
702 LocationSummary* summary = | 703 LocationSummary* summary = |
703 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 704 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
704 summary->set_in(0, Location::RequiresFpuRegister()); | 705 summary->set_in(0, Location::RequiresFpuRegister()); |
705 summary->set_in(1, Location::RequiresFpuRegister()); | 706 summary->set_in(1, Location::RequiresFpuRegister()); |
706 summary->set_out(0, Location::RequiresRegister()); | 707 summary->set_out(0, Location::RequiresRegister()); |
707 return summary; | 708 return summary; |
(...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1013 // element sizes > 1). | 1014 // element sizes > 1). |
1014 locs->set_in(1, (index_scale() == 1) | 1015 locs->set_in(1, (index_scale() == 1) |
1015 ? Location::WritableRegister() | 1016 ? Location::WritableRegister() |
1016 : Location::RequiresRegister()); | 1017 : Location::RequiresRegister()); |
1017 } | 1018 } |
1018 if ((representation() == kUnboxedDouble) || | 1019 if ((representation() == kUnboxedDouble) || |
1019 (representation() == kUnboxedFloat32x4) || | 1020 (representation() == kUnboxedFloat32x4) || |
1020 (representation() == kUnboxedInt32x4) || | 1021 (representation() == kUnboxedInt32x4) || |
1021 (representation() == kUnboxedFloat64x2)) { | 1022 (representation() == kUnboxedFloat64x2)) { |
1022 locs->set_out(0, Location::RequiresFpuRegister()); | 1023 locs->set_out(0, Location::RequiresFpuRegister()); |
1024 } else if (representation() == kUnboxedMint) { | |
1025 locs->set_out(0, Location::Pair(Location::RegisterLocation(EAX), | |
1026 Location::RegisterLocation(EDX))); | |
Florian Schneider
2014/05/21 12:50:59
For the case of Uint32Array you don't actually nee
Cutch
2014/05/21 17:00:03
Done.
| |
1023 } else { | 1027 } else { |
1028 ASSERT(representation() == kTagged); | |
1024 locs->set_out(0, Location::RequiresRegister()); | 1029 locs->set_out(0, Location::RequiresRegister()); |
1025 } | 1030 } |
1026 return locs; | 1031 return locs; |
1027 } | 1032 } |
1028 | 1033 |
1029 | 1034 |
1030 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1035 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
1031 Register array = locs()->in(0).reg(); | 1036 Register array = locs()->in(0).reg(); |
1032 Location index = locs()->in(1); | 1037 Location index = locs()->in(1); |
1033 | 1038 |
1034 Address element_address(kNoRegister, 0); | 1039 Address element_address(kNoRegister, 0); |
1035 if (IsExternal()) { | 1040 if (IsExternal()) { |
1036 element_address = index.IsRegister() | 1041 element_address = index.IsRegister() |
1037 ? FlowGraphCompiler::ExternalElementAddressForRegIndex( | 1042 ? FlowGraphCompiler::ExternalElementAddressForRegIndex( |
1038 index_scale(), array, index.reg()) | 1043 index_scale(), array, index.reg()) |
1039 : FlowGraphCompiler::ExternalElementAddressForIntIndex( | 1044 : FlowGraphCompiler::ExternalElementAddressForIntIndex( |
1040 index_scale(), array, Smi::Cast(index.constant()).Value()); | 1045 index_scale(), array, Smi::Cast(index.constant()).Value()); |
1041 } else { | 1046 } else { |
1042 ASSERT(this->array()->definition()->representation() == kTagged); | 1047 ASSERT(this->array()->definition()->representation() == kTagged); |
1043 element_address = index.IsRegister() | 1048 element_address = index.IsRegister() |
1044 ? FlowGraphCompiler::ElementAddressForRegIndex( | 1049 ? FlowGraphCompiler::ElementAddressForRegIndex( |
1045 class_id(), index_scale(), array, index.reg()) | 1050 class_id(), index_scale(), array, index.reg()) |
1046 : FlowGraphCompiler::ElementAddressForIntIndex( | 1051 : FlowGraphCompiler::ElementAddressForIntIndex( |
1047 class_id(), index_scale(), array, | 1052 class_id(), index_scale(), array, |
1048 Smi::Cast(index.constant()).Value()); | 1053 Smi::Cast(index.constant()).Value()); |
1049 } | 1054 } |
1050 | 1055 |
1051 if ((representation() == kUnboxedDouble) || | 1056 if ((representation() == kUnboxedDouble) || |
1052 (representation() == kUnboxedMint) || | |
1053 (representation() == kUnboxedFloat32x4) || | 1057 (representation() == kUnboxedFloat32x4) || |
1054 (representation() == kUnboxedInt32x4) || | 1058 (representation() == kUnboxedInt32x4) || |
1055 (representation() == kUnboxedFloat64x2)) { | 1059 (representation() == kUnboxedFloat64x2)) { |
1056 XmmRegister result = locs()->out(0).fpu_reg(); | 1060 XmmRegister result = locs()->out(0).fpu_reg(); |
1057 if ((index_scale() == 1) && index.IsRegister()) { | 1061 if ((index_scale() == 1) && index.IsRegister()) { |
1058 __ SmiUntag(index.reg()); | 1062 __ SmiUntag(index.reg()); |
1059 } | 1063 } |
1060 switch (class_id()) { | 1064 switch (class_id()) { |
1061 case kTypedDataInt32ArrayCid: | |
1062 __ movss(result, element_address); | |
1063 __ pmovsxdq(result, result); | |
1064 break; | |
1065 case kTypedDataUint32ArrayCid: | |
1066 __ xorpd(result, result); | |
1067 __ movss(result, element_address); | |
1068 break; | |
1069 case kTypedDataFloat32ArrayCid: | 1065 case kTypedDataFloat32ArrayCid: |
1070 __ movss(result, element_address); | 1066 __ movss(result, element_address); |
1071 break; | 1067 break; |
1072 case kTypedDataFloat64ArrayCid: | 1068 case kTypedDataFloat64ArrayCid: |
1073 __ movsd(result, element_address); | 1069 __ movsd(result, element_address); |
1074 break; | 1070 break; |
1075 case kTypedDataInt32x4ArrayCid: | 1071 case kTypedDataInt32x4ArrayCid: |
1076 case kTypedDataFloat32x4ArrayCid: | 1072 case kTypedDataFloat32x4ArrayCid: |
1077 case kTypedDataFloat64x2ArrayCid: | 1073 case kTypedDataFloat64x2ArrayCid: |
1078 __ movups(result, element_address); | 1074 __ movups(result, element_address); |
1079 break; | 1075 break; |
1076 default: | |
1077 UNREACHABLE(); | |
1080 } | 1078 } |
1081 return; | 1079 return; |
1082 } | 1080 } |
1083 | 1081 |
1082 if (representation() == kUnboxedMint) { | |
1083 ASSERT(locs()->out(0).IsPairLocation()); | |
1084 PairLocation* result_pair = locs()->out(0).AsPairLocation(); | |
1085 Register result1 = result_pair->At(0).reg(); | |
1086 Register result2 = result_pair->At(1).reg(); | |
1087 ASSERT(result1 == EAX); | |
1088 ASSERT(result2 == EDX); | |
Florian Schneider
2014/05/21 12:50:59
Move these two ASSERTs into the Int32Array case (w
Cutch
2014/05/21 17:00:03
Done.
| |
1089 if ((index_scale() == 1) && index.IsRegister()) { | |
1090 __ SmiUntag(index.reg()); | |
1091 } | |
1092 switch (class_id()) { | |
1093 case kTypedDataInt32ArrayCid: | |
1094 __ movl(result1, element_address); | |
1095 __ cdq(); | |
1096 break; | |
1097 case kTypedDataUint32ArrayCid: | |
1098 __ movl(result1, element_address); | |
1099 __ xorl(result2, result2); | |
1100 break; | |
1101 default: | |
1102 UNREACHABLE(); | |
1103 } | |
1104 return; | |
1105 } | |
1106 | |
1107 ASSERT(representation() == kTagged); | |
1108 | |
1084 Register result = locs()->out(0).reg(); | 1109 Register result = locs()->out(0).reg(); |
1085 if ((index_scale() == 1) && index.IsRegister()) { | 1110 if ((index_scale() == 1) && index.IsRegister()) { |
1086 __ SmiUntag(index.reg()); | 1111 __ SmiUntag(index.reg()); |
1087 } | 1112 } |
1088 switch (class_id()) { | 1113 switch (class_id()) { |
1089 case kTypedDataInt8ArrayCid: | 1114 case kTypedDataInt8ArrayCid: |
1090 ASSERT(index_scale() == 1); | 1115 ASSERT(index_scale() == 1); |
1091 __ movsxb(result, element_address); | 1116 __ movsxb(result, element_address); |
1092 __ SmiTag(result); | 1117 __ SmiTag(result); |
1093 break; | 1118 break; |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1205 // EBX, ECX, EDX) instead of using a fixed register. | 1230 // EBX, ECX, EDX) instead of using a fixed register. |
1206 locs->set_in(2, Location::FixedRegisterOrSmiConstant(value(), EAX)); | 1231 locs->set_in(2, Location::FixedRegisterOrSmiConstant(value(), EAX)); |
1207 break; | 1232 break; |
1208 case kTypedDataInt16ArrayCid: | 1233 case kTypedDataInt16ArrayCid: |
1209 case kTypedDataUint16ArrayCid: | 1234 case kTypedDataUint16ArrayCid: |
1210 // Writable register because the value must be untagged before storing. | 1235 // Writable register because the value must be untagged before storing. |
1211 locs->set_in(2, Location::WritableRegister()); | 1236 locs->set_in(2, Location::WritableRegister()); |
1212 break; | 1237 break; |
1213 case kTypedDataInt32ArrayCid: | 1238 case kTypedDataInt32ArrayCid: |
1214 case kTypedDataUint32ArrayCid: | 1239 case kTypedDataUint32ArrayCid: |
1215 // Mints are stored in XMM registers. For smis, use a writable register | 1240 // For smis, use a writable register because the value must be untagged |
1216 // because the value must be untagged before storing. | 1241 // before storing. Mints are stored in registers pairs. |
1217 locs->set_in(2, value()->IsSmiValue() | 1242 if (value()->IsSmiValue()) { |
1218 ? Location::WritableRegister() | 1243 locs->set_in(2, Location::WritableRegister()); |
1219 : Location::RequiresFpuRegister()); | 1244 } else { |
1245 // We only move the lower 32-bits so we don't care where the high bits | |
1246 // are located. | |
1247 locs->set_in(2, Location::Pair(Location::RequiresRegister(), | |
1248 Location::Any())); | |
1249 } | |
1220 break; | 1250 break; |
1221 case kTypedDataFloat32ArrayCid: | 1251 case kTypedDataFloat32ArrayCid: |
1222 case kTypedDataFloat64ArrayCid: | 1252 case kTypedDataFloat64ArrayCid: |
1223 // TODO(srdjan): Support Float64 constants. | 1253 // TODO(srdjan): Support Float64 constants. |
1224 locs->set_in(2, Location::RequiresFpuRegister()); | 1254 locs->set_in(2, Location::RequiresFpuRegister()); |
1225 break; | 1255 break; |
1226 case kTypedDataInt32x4ArrayCid: | 1256 case kTypedDataInt32x4ArrayCid: |
1227 case kTypedDataFloat32x4ArrayCid: | 1257 case kTypedDataFloat32x4ArrayCid: |
1228 case kTypedDataFloat64x2ArrayCid: | 1258 case kTypedDataFloat64x2ArrayCid: |
1229 locs->set_in(2, Location::RequiresFpuRegister()); | 1259 locs->set_in(2, Location::RequiresFpuRegister()); |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1326 } | 1356 } |
1327 case kTypedDataInt32ArrayCid: | 1357 case kTypedDataInt32ArrayCid: |
1328 case kTypedDataUint32ArrayCid: | 1358 case kTypedDataUint32ArrayCid: |
1329 if (value()->IsSmiValue()) { | 1359 if (value()->IsSmiValue()) { |
1330 ASSERT(RequiredInputRepresentation(2) == kTagged); | 1360 ASSERT(RequiredInputRepresentation(2) == kTagged); |
1331 Register value = locs()->in(2).reg(); | 1361 Register value = locs()->in(2).reg(); |
1332 __ SmiUntag(value); | 1362 __ SmiUntag(value); |
1333 __ movl(element_address, value); | 1363 __ movl(element_address, value); |
1334 } else { | 1364 } else { |
1335 ASSERT(RequiredInputRepresentation(2) == kUnboxedMint); | 1365 ASSERT(RequiredInputRepresentation(2) == kUnboxedMint); |
1336 __ movss(element_address, locs()->in(2).fpu_reg()); | 1366 PairLocation* value_pair = locs()->in(2).AsPairLocation(); |
1367 Register value1 = value_pair->At(0).reg(); | |
1368 __ movl(element_address, value1); | |
1337 } | 1369 } |
1338 break; | 1370 break; |
1339 case kTypedDataFloat32ArrayCid: | 1371 case kTypedDataFloat32ArrayCid: |
1340 __ movss(element_address, locs()->in(2).fpu_reg()); | 1372 __ movss(element_address, locs()->in(2).fpu_reg()); |
1341 break; | 1373 break; |
1342 case kTypedDataFloat64ArrayCid: | 1374 case kTypedDataFloat64ArrayCid: |
1343 __ movsd(element_address, locs()->in(2).fpu_reg()); | 1375 __ movsd(element_address, locs()->in(2).fpu_reg()); |
1344 break; | 1376 break; |
1345 case kTypedDataInt32x4ArrayCid: | 1377 case kTypedDataInt32x4ArrayCid: |
1346 case kTypedDataFloat32x4ArrayCid: | 1378 case kTypedDataFloat32x4ArrayCid: |
(...skipping 4182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5529 Register length = length_loc.reg(); | 5561 Register length = length_loc.reg(); |
5530 Register index = index_loc.reg(); | 5562 Register index = index_loc.reg(); |
5531 __ cmpl(index, length); | 5563 __ cmpl(index, length); |
5532 __ j(ABOVE_EQUAL, deopt); | 5564 __ j(ABOVE_EQUAL, deopt); |
5533 } | 5565 } |
5534 } | 5566 } |
5535 | 5567 |
5536 | 5568 |
5537 LocationSummary* UnboxIntegerInstr::MakeLocationSummary(bool opt) const { | 5569 LocationSummary* UnboxIntegerInstr::MakeLocationSummary(bool opt) const { |
5538 const intptr_t kNumInputs = 1; | 5570 const intptr_t kNumInputs = 1; |
5539 const intptr_t value_cid = value()->Type()->ToCid(); | 5571 const intptr_t kNumTemps = 0; |
5540 const bool needs_temp = ((value_cid != kSmiCid) && (value_cid != kMintCid)); | |
5541 const bool needs_writable_input = (value_cid == kSmiCid); | |
5542 const intptr_t kNumTemps = needs_temp ? 1 : 0; | |
5543 LocationSummary* summary = | 5572 LocationSummary* summary = |
5544 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5573 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5545 summary->set_in(0, needs_writable_input | 5574 summary->set_in(0, Location::RequiresRegister()); |
5546 ? Location::WritableRegister() | 5575 summary->set_out(0, Location::Pair(Location::RegisterLocation(EAX), |
5547 : Location::RequiresRegister()); | 5576 Location::RegisterLocation(EDX))); |
5548 if (needs_temp) { | |
5549 summary->set_temp(0, Location::RequiresRegister()); | |
5550 } | |
5551 summary->set_out(0, Location::RequiresFpuRegister()); | |
5552 return summary; | 5577 return summary; |
5553 } | 5578 } |
5554 | 5579 |
5555 | 5580 |
5556 void UnboxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5581 void UnboxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5557 const intptr_t value_cid = value()->Type()->ToCid(); | 5582 const intptr_t value_cid = value()->Type()->ToCid(); |
5558 const Register value = locs()->in(0).reg(); | 5583 const Register value = locs()->in(0).reg(); |
5559 const XmmRegister result = locs()->out(0).fpu_reg(); | 5584 PairLocation* result_pair = locs()->out(0).AsPairLocation(); |
5585 Register result_lo = result_pair->At(0).reg(); | |
5586 Register result_hi = result_pair->At(1).reg(); | |
5587 | |
5588 ASSERT(value != result_lo); | |
5589 ASSERT(value != result_hi); | |
5590 ASSERT(result_lo == EAX); | |
5591 ASSERT(result_hi == EDX); | |
5560 | 5592 |
5561 if (value_cid == kMintCid) { | 5593 if (value_cid == kMintCid) { |
5562 __ movsd(result, FieldAddress(value, Mint::value_offset())); | 5594 __ movl(result_lo, FieldAddress(value, Mint::value_offset())); |
5595 __ movl(result_hi, FieldAddress(value, Mint::value_offset() + kWordSize)); | |
5563 } else if (value_cid == kSmiCid) { | 5596 } else if (value_cid == kSmiCid) { |
5564 __ SmiUntag(value); // Untag input before conversion. | 5597 __ movl(result_lo, value); |
5565 __ movd(result, value); | 5598 __ SmiUntag(result_lo); |
5566 __ pmovsxdq(result, result); | 5599 // Sign extend into result_hi. |
5600 __ cdq(); | |
5567 } else { | 5601 } else { |
5568 Register temp = locs()->temp(0).reg(); | |
5569 Label* deopt = compiler->AddDeoptStub(deopt_id_, | 5602 Label* deopt = compiler->AddDeoptStub(deopt_id_, |
5570 ICData::kDeoptUnboxInteger); | 5603 ICData::kDeoptUnboxInteger); |
5571 Label is_smi, done; | 5604 Label is_smi, done; |
5572 __ testl(value, Immediate(kSmiTagMask)); | 5605 __ testl(value, Immediate(kSmiTagMask)); |
5573 __ j(ZERO, &is_smi); | 5606 __ j(ZERO, &is_smi); |
5574 __ CompareClassId(value, kMintCid, temp); | 5607 __ CompareClassId(value, kMintCid, result_lo); |
5575 __ j(NOT_EQUAL, deopt); | 5608 __ j(NOT_EQUAL, deopt); |
5576 __ movsd(result, FieldAddress(value, Mint::value_offset())); | 5609 __ movl(result_lo, FieldAddress(value, Mint::value_offset())); |
5610 __ movl(result_hi, FieldAddress(value, Mint::value_offset() + kWordSize)); | |
5577 __ jmp(&done); | 5611 __ jmp(&done); |
5578 __ Bind(&is_smi); | 5612 __ Bind(&is_smi); |
5579 __ movl(temp, value); | 5613 __ movl(result_lo, value); |
5580 __ SmiUntag(temp); | 5614 __ SmiUntag(result_lo); |
5581 __ movd(result, temp); | 5615 // Sign extend into result_hi. |
5582 __ pmovsxdq(result, result); | 5616 __ cdq(); |
5583 __ Bind(&done); | 5617 __ Bind(&done); |
5584 } | 5618 } |
5585 } | 5619 } |
5586 | 5620 |
5587 | 5621 |
5588 LocationSummary* BoxIntegerInstr::MakeLocationSummary(bool opt) const { | 5622 LocationSummary* BoxIntegerInstr::MakeLocationSummary(bool opt) const { |
5589 const intptr_t kNumInputs = 1; | 5623 const intptr_t kNumInputs = 1; |
5590 const intptr_t kNumTemps = 2; | 5624 const intptr_t kNumTemps = 1; |
5591 LocationSummary* summary = | 5625 LocationSummary* summary = |
5592 new LocationSummary(kNumInputs, | 5626 new LocationSummary(kNumInputs, |
5593 kNumTemps, | 5627 kNumTemps, |
5594 LocationSummary::kCallOnSlowPath); | 5628 LocationSummary::kCallOnSlowPath); |
5595 summary->set_in(0, Location::RequiresFpuRegister()); | 5629 summary->set_in(0, Location::Pair(Location::RegisterLocation(EAX), |
5596 summary->set_temp(0, Location::RegisterLocation(EAX)); | 5630 Location::RegisterLocation(EDX))); |
5597 summary->set_temp(1, Location::RegisterLocation(EDX)); | 5631 summary->set_temp(0, Location::RequiresRegister()); |
5598 // TODO(fschneider): Save one temp by using result register as a temp. | |
5599 summary->set_out(0, Location::RequiresRegister()); | 5632 summary->set_out(0, Location::RequiresRegister()); |
5600 return summary; | 5633 return summary; |
5601 } | 5634 } |
5602 | 5635 |
5603 | 5636 |
5604 class BoxIntegerSlowPath : public SlowPathCode { | 5637 class BoxIntegerSlowPath : public SlowPathCode { |
5605 public: | 5638 public: |
5606 explicit BoxIntegerSlowPath(BoxIntegerInstr* instruction) | 5639 explicit BoxIntegerSlowPath(BoxIntegerInstr* instruction) |
5607 : instruction_(instruction) { } | 5640 : instruction_(instruction) { } |
5608 | 5641 |
(...skipping 21 matching lines...) Expand all Loading... | |
5630 } | 5663 } |
5631 | 5664 |
5632 private: | 5665 private: |
5633 BoxIntegerInstr* instruction_; | 5666 BoxIntegerInstr* instruction_; |
5634 }; | 5667 }; |
5635 | 5668 |
5636 | 5669 |
5637 void BoxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5670 void BoxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5638 BoxIntegerSlowPath* slow_path = new BoxIntegerSlowPath(this); | 5671 BoxIntegerSlowPath* slow_path = new BoxIntegerSlowPath(this); |
5639 compiler->AddSlowPathCode(slow_path); | 5672 compiler->AddSlowPathCode(slow_path); |
5673 PairLocation* value_pair = locs()->in(0).AsPairLocation(); | |
5674 Register value_lo = value_pair->At(0).reg(); | |
5675 Register value_hi = value_pair->At(1).reg(); | |
5676 Register out_reg = locs()->out(0).reg(); | |
5640 | 5677 |
5641 Register out_reg = locs()->out(0).reg(); | 5678 ASSERT(value_lo == EAX); |
Florian Schneider
2014/05/21 12:50:59
Where is it assumed that value_lo must be EAX? It
Cutch
2014/05/21 17:00:03
Done.
| |
5642 XmmRegister value = locs()->in(0).fpu_reg(); | 5679 ASSERT(value_hi == EDX); |
Florian Schneider
2014/05/21 12:50:59
Same for value_hi.
Cutch
2014/05/21 17:00:03
Done.
| |
5680 | |
5681 // Copy value_hi into out_reg as a temporary. | |
5682 // We modify value_lo but restore it before using it. | |
5683 __ movl(out_reg, value_hi); | |
5643 | 5684 |
5644 // Unboxed operations produce smis or mint-sized values. | 5685 // Unboxed operations produce smis or mint-sized values. |
5645 // Check if value fits into a smi. | 5686 // Check if value fits into a smi. |
5646 Label not_smi, done; | 5687 Label not_smi, done; |
5647 __ pextrd(EDX, value, Immediate(1)); // Upper half. | 5688 |
5648 __ pextrd(EAX, value, Immediate(0)); // Lower half. | |
5649 // 1. Compute (x + -kMinSmi) which has to be in the range | 5689 // 1. Compute (x + -kMinSmi) which has to be in the range |
5650 // 0 .. -kMinSmi+kMaxSmi for x to fit into a smi. | 5690 // 0 .. -kMinSmi+kMaxSmi for x to fit into a smi. |
5651 __ addl(EAX, Immediate(0x40000000)); | 5691 __ addl(value_lo, Immediate(0x40000000)); |
5652 __ adcl(EDX, Immediate(0)); | 5692 __ adcl(out_reg, Immediate(0)); |
5653 // 2. Unsigned compare to -kMinSmi+kMaxSmi. | 5693 // 2. Unsigned compare to -kMinSmi+kMaxSmi. |
5654 __ cmpl(EAX, Immediate(0x80000000)); | 5694 __ cmpl(value_lo, Immediate(0x80000000)); |
5655 __ sbbl(EDX, Immediate(0)); | 5695 __ sbbl(out_reg, Immediate(0)); |
5656 __ j(ABOVE_EQUAL, ¬_smi); | 5696 __ j(ABOVE_EQUAL, ¬_smi); |
5657 // 3. Restore lower half if result is a smi. | 5697 // 3. Restore lower half if result is a smi. |
5658 __ subl(EAX, Immediate(0x40000000)); | 5698 __ subl(value_lo, Immediate(0x40000000)); |
5659 | 5699 __ movl(out_reg, value_lo); |
5660 __ SmiTag(EAX); | 5700 __ SmiTag(out_reg); |
5661 __ movl(out_reg, EAX); | |
5662 __ jmp(&done); | 5701 __ jmp(&done); |
5663 | |
5664 __ Bind(¬_smi); | 5702 __ Bind(¬_smi); |
5665 __ TryAllocate( | 5703 __ TryAllocate( |
5666 Class::ZoneHandle(Isolate::Current()->object_store()->mint_class()), | 5704 Class::ZoneHandle(Isolate::Current()->object_store()->mint_class()), |
5667 slow_path->entry_label(), | 5705 slow_path->entry_label(), |
5668 Assembler::kFarJump, | 5706 Assembler::kFarJump, |
5669 out_reg, | 5707 out_reg, |
5670 kNoRegister); | 5708 kNoRegister); |
5671 __ Bind(slow_path->exit_label()); | 5709 __ Bind(slow_path->exit_label()); |
5672 __ movsd(FieldAddress(out_reg, Mint::value_offset()), value); | 5710 // 3. Restore lower half of input before using it. |
5711 __ subl(value_lo, Immediate(0x40000000)); | |
5712 __ movl(FieldAddress(out_reg, Mint::value_offset()), value_lo); | |
5713 __ movl(FieldAddress(out_reg, Mint::value_offset() + kWordSize), value_hi); | |
5673 __ Bind(&done); | 5714 __ Bind(&done); |
5674 } | 5715 } |
5675 | 5716 |
5676 | 5717 |
5677 LocationSummary* BinaryMintOpInstr::MakeLocationSummary(bool opt) const { | 5718 LocationSummary* BinaryMintOpInstr::MakeLocationSummary(bool opt) const { |
5678 const intptr_t kNumInputs = 2; | 5719 const intptr_t kNumInputs = 2; |
5679 switch (op_kind()) { | 5720 switch (op_kind()) { |
5680 case Token::kBIT_AND: | 5721 case Token::kBIT_AND: |
5681 case Token::kBIT_OR: | 5722 case Token::kBIT_OR: |
5682 case Token::kBIT_XOR: { | 5723 case Token::kBIT_XOR: { |
5683 const intptr_t kNumTemps = | 5724 const intptr_t kNumTemps = 0; |
5684 FLAG_throw_on_javascript_int_overflow ? 1 : 0; | |
5685 LocationSummary* summary = | 5725 LocationSummary* summary = |
5686 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5726 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5687 summary->set_in(0, Location::RequiresFpuRegister()); | 5727 summary->set_in(0, Location::Pair(Location::RequiresRegister(), |
5688 summary->set_in(1, Location::RequiresFpuRegister()); | 5728 Location::RequiresRegister())); |
5689 if (FLAG_throw_on_javascript_int_overflow) { | 5729 summary->set_in(1, Location::Pair(Location::RequiresRegister(), |
5690 summary->set_temp(0, Location::RequiresRegister()); | 5730 Location::RequiresRegister())); |
5691 } | |
5692 summary->set_out(0, Location::SameAsFirstInput()); | 5731 summary->set_out(0, Location::SameAsFirstInput()); |
5693 return summary; | 5732 return summary; |
5694 } | 5733 } |
5695 case Token::kADD: | 5734 case Token::kADD: |
5696 case Token::kSUB: { | 5735 case Token::kSUB: { |
5697 const intptr_t kNumTemps = 2; | 5736 const intptr_t kNumTemps = 0; |
5698 LocationSummary* summary = | 5737 LocationSummary* summary = |
5699 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5738 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5700 summary->set_in(0, Location::RequiresFpuRegister()); | 5739 summary->set_in(0, Location::Pair(Location::RequiresRegister(), |
5701 summary->set_in(1, Location::RequiresFpuRegister()); | 5740 Location::RequiresRegister())); |
5702 summary->set_temp(0, Location::RequiresRegister()); | 5741 summary->set_in(1, Location::Pair(Location::RequiresRegister(), |
5703 summary->set_temp(1, Location::RequiresRegister()); | 5742 Location::RequiresRegister())); |
5704 summary->set_out(0, Location::SameAsFirstInput()); | 5743 summary->set_out(0, Location::SameAsFirstInput()); |
5705 return summary; | 5744 return summary; |
5706 } | 5745 } |
5707 default: | 5746 default: |
5708 UNREACHABLE(); | 5747 UNREACHABLE(); |
5709 return NULL; | 5748 return NULL; |
5710 } | 5749 } |
5711 } | 5750 } |
5712 | 5751 |
5713 | 5752 |
5714 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5753 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5715 XmmRegister left = locs()->in(0).fpu_reg(); | 5754 PairLocation* left_pair = locs()->in(0).AsPairLocation(); |
5716 XmmRegister right = locs()->in(1).fpu_reg(); | 5755 Register left_lo = left_pair->At(0).reg(); |
5717 | 5756 Register left_hi = left_pair->At(1).reg(); |
5718 ASSERT(locs()->out(0).fpu_reg() == left); | 5757 PairLocation* right_pair = locs()->in(1).AsPairLocation(); |
5758 Register right_lo = right_pair->At(0).reg(); | |
5759 Register right_hi = right_pair->At(1).reg(); | |
5760 PairLocation* out_pair = locs()->out(0).AsPairLocation(); | |
5761 Register out_lo = out_pair->At(0).reg(); | |
5762 Register out_hi = out_pair->At(1).reg(); | |
5763 ASSERT(out_lo == left_lo); | |
5764 ASSERT(out_hi == left_hi); | |
5719 | 5765 |
5720 Label* deopt = NULL; | 5766 Label* deopt = NULL; |
5721 if (FLAG_throw_on_javascript_int_overflow) { | 5767 if (FLAG_throw_on_javascript_int_overflow) { |
5722 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp); | 5768 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp); |
5723 } | 5769 } |
5724 switch (op_kind()) { | 5770 switch (op_kind()) { |
5725 case Token::kBIT_AND: __ andpd(left, right); break; | 5771 case Token::kBIT_AND: |
5726 case Token::kBIT_OR: __ orpd(left, right); break; | 5772 __ andl(left_lo, right_lo); |
5727 case Token::kBIT_XOR: __ xorpd(left, right); break; | 5773 __ andl(left_hi, right_hi); |
5774 break; | |
5775 case Token::kBIT_OR: | |
5776 __ orl(left_lo, right_lo); | |
5777 __ orl(left_hi, right_hi); | |
5778 break; | |
5779 case Token::kBIT_XOR: | |
5780 __ xorl(left_lo, right_lo); | |
5781 __ xorl(left_hi, right_hi); | |
5782 break; | |
5728 case Token::kADD: | 5783 case Token::kADD: |
5729 case Token::kSUB: { | 5784 case Token::kSUB: { |
5730 Register lo = locs()->temp(0).reg(); | |
5731 Register hi = locs()->temp(1).reg(); | |
5732 if (!FLAG_throw_on_javascript_int_overflow) { | 5785 if (!FLAG_throw_on_javascript_int_overflow) { |
5733 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp); | 5786 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp); |
5734 } | 5787 } |
5735 | |
5736 Label done, overflow; | |
5737 __ pextrd(lo, right, Immediate(0)); // Lower half | |
5738 __ pextrd(hi, right, Immediate(1)); // Upper half | |
5739 __ subl(ESP, Immediate(2 * kWordSize)); | |
5740 __ movq(Address(ESP, 0), left); | |
5741 if (op_kind() == Token::kADD) { | 5788 if (op_kind() == Token::kADD) { |
5742 __ addl(Address(ESP, 0), lo); | 5789 __ addl(left_lo, right_lo); |
5743 __ adcl(Address(ESP, 1 * kWordSize), hi); | 5790 __ adcl(left_hi, right_hi); |
5744 } else { | 5791 } else { |
5745 __ subl(Address(ESP, 0), lo); | 5792 __ subl(left_lo, right_lo); |
5746 __ sbbl(Address(ESP, 1 * kWordSize), hi); | 5793 __ sbbl(left_hi, right_hi); |
5747 } | 5794 } |
5748 __ j(OVERFLOW, &overflow); | 5795 __ j(OVERFLOW, deopt); |
5749 __ movq(left, Address(ESP, 0)); | |
5750 __ addl(ESP, Immediate(2 * kWordSize)); | |
5751 __ jmp(&done); | |
5752 __ Bind(&overflow); | |
5753 __ addl(ESP, Immediate(2 * kWordSize)); | |
5754 __ jmp(deopt); | |
5755 __ Bind(&done); | |
5756 break; | 5796 break; |
5757 } | 5797 } |
5758 default: UNREACHABLE(); | 5798 default: UNREACHABLE(); |
5759 } | 5799 } |
5760 if (FLAG_throw_on_javascript_int_overflow) { | 5800 if (FLAG_throw_on_javascript_int_overflow) { |
5761 Register tmp = locs()->temp(0).reg(); | 5801 EmitJavascriptIntOverflowCheck(compiler, deopt, left_lo, left_hi); |
5762 EmitJavascriptIntOverflowCheck(compiler, deopt, left, tmp); | |
5763 } | 5802 } |
5764 } | 5803 } |
5765 | 5804 |
5766 | 5805 |
5767 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(bool opt) const { | 5806 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(bool opt) const { |
5768 const intptr_t kNumInputs = 2; | 5807 const intptr_t kNumInputs = 2; |
5769 const intptr_t kNumTemps = op_kind() == Token::kSHL ? 2 : 1; | 5808 const intptr_t kNumTemps = op_kind() == Token::kSHL ? 2 : 0; |
5770 LocationSummary* summary = | 5809 LocationSummary* summary = |
5771 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5810 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5772 summary->set_in(0, Location::RequiresFpuRegister()); | 5811 summary->set_in(0, Location::Pair(Location::RequiresRegister(), |
5812 Location::RequiresRegister())); | |
5773 summary->set_in(1, Location::RegisterLocation(ECX)); | 5813 summary->set_in(1, Location::RegisterLocation(ECX)); |
5774 summary->set_temp(0, Location::RequiresRegister()); | |
5775 if (op_kind() == Token::kSHL) { | 5814 if (op_kind() == Token::kSHL) { |
5815 summary->set_temp(0, Location::RequiresRegister()); | |
5776 summary->set_temp(1, Location::RequiresRegister()); | 5816 summary->set_temp(1, Location::RequiresRegister()); |
5777 } | 5817 } |
5778 summary->set_out(0, Location::SameAsFirstInput()); | 5818 summary->set_out(0, Location::SameAsFirstInput()); |
5779 return summary; | 5819 return summary; |
5780 } | 5820 } |
5781 | 5821 |
5782 | 5822 |
5783 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5823 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5784 XmmRegister left = locs()->in(0).fpu_reg(); | 5824 PairLocation* left_pair = locs()->in(0).AsPairLocation(); |
5785 ASSERT(locs()->in(1).reg() == ECX); | 5825 Register left_lo = left_pair->At(0).reg(); |
5786 ASSERT(locs()->out(0).fpu_reg() == left); | 5826 Register left_hi = left_pair->At(1).reg(); |
5827 PairLocation* out_pair = locs()->out(0).AsPairLocation(); | |
5828 Register out_lo = out_pair->At(0).reg(); | |
5829 Register out_hi = out_pair->At(1).reg(); | |
5830 ASSERT(out_lo == left_lo); | |
5831 ASSERT(out_hi == left_hi); | |
5787 | 5832 |
5788 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptShiftMintOp); | 5833 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptShiftMintOp); |
5789 Label done; | 5834 Label done; |
5790 __ testl(ECX, ECX); | 5835 __ testl(ECX, ECX); |
5791 __ j(ZERO, &done); // Shift by 0 is a nop. | 5836 __ j(ZERO, &done); // Shift by 0 is a nop. |
5792 __ subl(ESP, Immediate(2 * kWordSize)); | |
5793 __ movq(Address(ESP, 0), left); | |
5794 // Deoptimize if shift count is > 31. | 5837 // Deoptimize if shift count is > 31. |
5795 // sarl operation masks the count to 5 bits and | 5838 // sarl operation masks the count to 5 bits and |
5796 // shrd is undefined with count > operand size (32) | 5839 // shrd is undefined with count > operand size (32) |
5797 // TODO(fschneider): Support shift counts > 31 without deoptimization. | 5840 // TODO(fschneider): Support shift counts > 31 without deoptimization. |
5798 __ SmiUntag(ECX); | 5841 __ SmiUntag(ECX); |
5799 const Immediate& kCountLimit = Immediate(31); | 5842 const Immediate& kCountLimit = Immediate(31); |
5800 __ cmpl(ECX, kCountLimit); | 5843 __ cmpl(ECX, kCountLimit); |
5801 __ j(ABOVE, deopt); | 5844 __ j(ABOVE, deopt); |
5802 switch (op_kind()) { | 5845 switch (op_kind()) { |
5803 case Token::kSHR: { | 5846 case Token::kSHR: { |
5804 Register temp = locs()->temp(0).reg(); | 5847 __ shrd(left_lo, left_hi); // Shift count in CL. |
5805 __ movl(temp, Address(ESP, 1 * kWordSize)); // High half. | 5848 __ sarl(left_hi, ECX); // Shift count in CL. |
5806 __ shrd(Address(ESP, 0), temp); // Shift count in CL. | |
5807 __ sarl(Address(ESP, 1 * kWordSize), ECX); // Shift count in CL. | |
5808 break; | 5849 break; |
5809 } | 5850 } |
5810 case Token::kSHL: { | 5851 case Token::kSHL: { |
5811 Register temp1 = locs()->temp(0).reg(); | 5852 Register temp1 = locs()->temp(0).reg(); |
5812 Register temp2 = locs()->temp(1).reg(); | 5853 Register temp2 = locs()->temp(1).reg(); |
5813 __ movl(temp1, Address(ESP, 0 * kWordSize)); // Low 32 bits. | 5854 __ movl(temp1, left_lo); // Low 32 bits. |
5814 __ movl(temp2, Address(ESP, 1 * kWordSize)); // High 32 bits. | 5855 __ movl(temp2, left_hi); // High 32 bits. |
5815 __ shll(Address(ESP, 0 * kWordSize), ECX); // Shift count in CL. | 5856 __ shll(left_lo, ECX); // Shift count in CL. |
5816 __ shld(Address(ESP, 1 * kWordSize), temp1); // Shift count in CL. | 5857 __ shld(left_hi, temp1); // Shift count in CL. |
5817 // Check for overflow by shifting back the high 32 bits | 5858 // Check for overflow by shifting back the high 32 bits |
5818 // and comparing with the input. | 5859 // and comparing with the input. |
5819 __ movl(temp1, temp2); | 5860 __ movl(temp1, temp2); |
5820 __ movl(temp2, Address(ESP, 1 * kWordSize)); | 5861 __ movl(temp2, left_hi); |
5821 __ sarl(temp2, ECX); | 5862 __ sarl(temp2, ECX); |
5822 __ cmpl(temp1, temp2); | 5863 __ cmpl(temp1, temp2); |
5823 __ j(NOT_EQUAL, deopt); | 5864 __ j(NOT_EQUAL, deopt); |
5824 break; | 5865 break; |
5825 } | 5866 } |
5826 default: | 5867 default: |
5827 UNREACHABLE(); | 5868 UNREACHABLE(); |
5828 break; | 5869 break; |
5829 } | 5870 } |
5830 __ movq(left, Address(ESP, 0)); | |
5831 __ addl(ESP, Immediate(2 * kWordSize)); | |
5832 __ Bind(&done); | 5871 __ Bind(&done); |
5833 if (FLAG_throw_on_javascript_int_overflow) { | 5872 if (FLAG_throw_on_javascript_int_overflow) { |
5834 Register tmp = locs()->temp(0).reg(); | 5873 EmitJavascriptIntOverflowCheck(compiler, deopt, left_lo, left_hi); |
5835 EmitJavascriptIntOverflowCheck(compiler, deopt, left, tmp); | |
5836 } | 5874 } |
5837 } | 5875 } |
5838 | 5876 |
5839 | 5877 |
5840 LocationSummary* UnaryMintOpInstr::MakeLocationSummary(bool opt) const { | 5878 LocationSummary* UnaryMintOpInstr::MakeLocationSummary(bool opt) const { |
5841 const intptr_t kNumInputs = 1; | 5879 const intptr_t kNumInputs = 1; |
5842 const intptr_t kNumTemps = | 5880 const intptr_t kNumTemps = 0; |
5843 FLAG_throw_on_javascript_int_overflow ? 1 : 0; | |
5844 LocationSummary* summary = | 5881 LocationSummary* summary = |
5845 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5882 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5846 summary->set_in(0, Location::RequiresFpuRegister()); | 5883 summary->set_in(0, Location::Pair(Location::RequiresRegister(), |
5884 Location::RequiresRegister())); | |
5847 summary->set_out(0, Location::SameAsFirstInput()); | 5885 summary->set_out(0, Location::SameAsFirstInput()); |
5848 if (FLAG_throw_on_javascript_int_overflow) { | 5886 if (FLAG_throw_on_javascript_int_overflow) { |
5849 summary->set_temp(0, Location::RequiresRegister()); | 5887 summary->set_temp(0, Location::RequiresRegister()); |
5850 } | 5888 } |
5851 return summary; | 5889 return summary; |
5852 } | 5890 } |
5853 | 5891 |
5854 | 5892 |
5855 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5893 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5856 ASSERT(op_kind() == Token::kBIT_NOT); | 5894 ASSERT(op_kind() == Token::kBIT_NOT); |
5857 XmmRegister value = locs()->in(0).fpu_reg(); | 5895 PairLocation* left_pair = locs()->in(0).AsPairLocation(); |
5858 ASSERT(value == locs()->out(0).fpu_reg()); | 5896 Register left_lo = left_pair->At(0).reg(); |
5897 Register left_hi = left_pair->At(1).reg(); | |
5898 PairLocation* out_pair = locs()->out(0).AsPairLocation(); | |
5899 Register out_lo = out_pair->At(0).reg(); | |
5900 Register out_hi = out_pair->At(1).reg(); | |
5901 ASSERT(out_lo == left_lo); | |
5902 ASSERT(out_hi == left_hi); | |
5903 | |
5859 Label* deopt = NULL; | 5904 Label* deopt = NULL; |
5860 if (FLAG_throw_on_javascript_int_overflow) { | 5905 if (FLAG_throw_on_javascript_int_overflow) { |
5861 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryMintOp); | 5906 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryMintOp); |
5862 } | 5907 } |
5863 __ pcmpeqq(XMM0, XMM0); // Generate all 1's. | 5908 |
5864 __ pxor(value, XMM0); | 5909 __ notl(left_lo); |
5910 __ notl(left_hi); | |
5911 | |
5865 if (FLAG_throw_on_javascript_int_overflow) { | 5912 if (FLAG_throw_on_javascript_int_overflow) { |
5866 Register tmp = locs()->temp(0).reg(); | 5913 EmitJavascriptIntOverflowCheck(compiler, deopt, left_lo, left_hi); |
5867 EmitJavascriptIntOverflowCheck(compiler, deopt, value, tmp); | |
5868 } | 5914 } |
5869 } | 5915 } |
5870 | 5916 |
5871 | 5917 |
5872 LocationSummary* ThrowInstr::MakeLocationSummary(bool opt) const { | 5918 LocationSummary* ThrowInstr::MakeLocationSummary(bool opt) const { |
5873 return new LocationSummary(0, 0, LocationSummary::kCall); | 5919 return new LocationSummary(0, 0, LocationSummary::kCall); |
5874 } | 5920 } |
5875 | 5921 |
5876 | 5922 |
5877 | 5923 |
(...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6192 PcDescriptors::kOther, | 6238 PcDescriptors::kOther, |
6193 locs()); | 6239 locs()); |
6194 __ Drop(ArgumentCount()); // Discard arguments. | 6240 __ Drop(ArgumentCount()); // Discard arguments. |
6195 } | 6241 } |
6196 | 6242 |
6197 } // namespace dart | 6243 } // namespace dart |
6198 | 6244 |
6199 #undef __ | 6245 #undef __ |
6200 | 6246 |
6201 #endif // defined TARGET_ARCH_IA32 | 6247 #endif // defined TARGET_ARCH_IA32 |
OLD | NEW |