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 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
216 default: | 216 default: |
217 UNREACHABLE(); | 217 UNREACHABLE(); |
218 return OVERFLOW; | 218 return OVERFLOW; |
219 } | 219 } |
220 } | 220 } |
221 | 221 |
222 | 222 |
223 LocationSummary* EqualityCompareInstr::MakeLocationSummary(bool opt) const { | 223 LocationSummary* EqualityCompareInstr::MakeLocationSummary(bool opt) const { |
224 const intptr_t kNumInputs = 2; | 224 const intptr_t kNumInputs = 2; |
225 if (operation_cid() == kMintCid) { | 225 if (operation_cid() == kMintCid) { |
226 const intptr_t kNumTemps = 1; | 226 const intptr_t kNumTemps = 0; |
227 LocationSummary* locs = | 227 LocationSummary* locs = |
228 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 228 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
229 locs->set_in(0, Location::RequiresFpuRegister()); | 229 locs->set_in(0, Location::Pair(Location::RequiresRegister(), |
230 locs->set_in(1, Location::RequiresFpuRegister()); | 230 Location::RequiresRegister())); |
231 locs->set_temp(0, Location::RequiresRegister()); | 231 locs->set_in(1, Location::Pair(Location::RequiresRegister(), |
232 Location::RequiresRegister())); | |
232 locs->set_out(0, Location::RequiresRegister()); | 233 locs->set_out(0, Location::RequiresRegister()); |
233 return locs; | 234 return locs; |
234 } | 235 } |
235 if (operation_cid() == kDoubleCid) { | 236 if (operation_cid() == kDoubleCid) { |
236 const intptr_t kNumTemps = 0; | 237 const intptr_t kNumTemps = 0; |
237 LocationSummary* locs = | 238 LocationSummary* locs = |
238 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 239 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
239 locs->set_in(0, Location::RequiresFpuRegister()); | 240 locs->set_in(0, Location::RequiresFpuRegister()); |
240 locs->set_in(1, Location::RequiresFpuRegister()); | 241 locs->set_in(1, Location::RequiresFpuRegister()); |
241 locs->set_out(0, Location::RequiresRegister()); | 242 locs->set_out(0, Location::RequiresRegister()); |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
355 __ cmpl(left.reg(), right.ToStackSlotAddress()); | 356 __ cmpl(left.reg(), right.ToStackSlotAddress()); |
356 } else { | 357 } else { |
357 __ cmpl(left.reg(), right.reg()); | 358 __ cmpl(left.reg(), right.reg()); |
358 } | 359 } |
359 return true_condition; | 360 return true_condition; |
360 } | 361 } |
361 | 362 |
362 | 363 |
363 static void EmitJavascriptIntOverflowCheck(FlowGraphCompiler* compiler, | 364 static void EmitJavascriptIntOverflowCheck(FlowGraphCompiler* compiler, |
364 Label* overflow, | 365 Label* overflow, |
365 XmmRegister result, | 366 Register result_lo, |
367 Register result_hi, | |
366 Register tmp) { | 368 Register tmp) { |
367 // Compare upper half. | 369 // Compare upper half. |
368 Label check_lower; | 370 Label check_lower; |
369 __ pextrd(tmp, result, Immediate(1)); | 371 __ movl(tmp, result_hi); |
Florian Schneider
2014/04/30 18:55:46
I think tmp is not needed anymore here.
Cutch
2014/05/14 17:16:19
Done.
| |
370 __ cmpl(tmp, Immediate(0x00200000)); | 372 __ cmpl(tmp, Immediate(0x00200000)); |
371 __ j(GREATER, overflow); | 373 __ j(GREATER, overflow); |
372 __ j(NOT_EQUAL, &check_lower); | 374 __ j(NOT_EQUAL, &check_lower); |
373 | 375 |
374 __ pextrd(tmp, result, Immediate(0)); | 376 __ movl(tmp, result_lo); |
375 __ cmpl(tmp, Immediate(0)); | 377 __ cmpl(tmp, Immediate(0)); |
376 __ j(ABOVE, overflow); | 378 __ j(ABOVE, overflow); |
377 | 379 |
378 __ Bind(&check_lower); | 380 __ Bind(&check_lower); |
379 __ pextrd(tmp, result, Immediate(1)); | 381 __ movl(tmp, result_hi); |
380 __ cmpl(tmp, Immediate(-0x00200000)); | 382 __ cmpl(tmp, Immediate(-0x00200000)); |
381 __ j(LESS, overflow); | 383 __ j(LESS, overflow); |
382 // Anything in the lower part would make the number bigger than the lower | 384 // Anything in the lower part would make the number bigger than the lower |
383 // bound, so we are done. | 385 // bound, so we are done. |
384 } | 386 } |
385 | 387 |
386 | 388 |
387 static Condition TokenKindToMintCondition(Token::Kind kind) { | 389 static Condition TokenKindToMintCondition(Token::Kind kind) { |
388 switch (kind) { | 390 switch (kind) { |
389 case Token::kEQ: return EQUAL; | 391 case Token::kEQ: return EQUAL; |
390 case Token::kNE: return NOT_EQUAL; | 392 case Token::kNE: return NOT_EQUAL; |
391 case Token::kLT: return LESS; | 393 case Token::kLT: return LESS; |
392 case Token::kGT: return GREATER; | 394 case Token::kGT: return GREATER; |
393 case Token::kLTE: return LESS_EQUAL; | 395 case Token::kLTE: return LESS_EQUAL; |
394 case Token::kGTE: return GREATER_EQUAL; | 396 case Token::kGTE: return GREATER_EQUAL; |
395 default: | 397 default: |
396 UNREACHABLE(); | 398 UNREACHABLE(); |
397 return OVERFLOW; | 399 return OVERFLOW; |
398 } | 400 } |
399 } | 401 } |
400 | 402 |
401 | 403 |
402 static Condition EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler, | 404 static Condition EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler, |
403 const LocationSummary& locs, | 405 const LocationSummary& locs, |
404 Token::Kind kind, | 406 Token::Kind kind, |
405 BranchLabels labels) { | 407 BranchLabels labels) { |
406 ASSERT(Token::IsEqualityOperator(kind)); | 408 ASSERT(Token::IsEqualityOperator(kind)); |
407 XmmRegister left = locs.in(0).fpu_reg(); | 409 PairLocation* left_pair = locs.in(0).AsPairLocation(); |
408 XmmRegister right = locs.in(1).fpu_reg(); | 410 Register left1 = left_pair->At(0).reg(); |
409 Register temp = locs.temp(0).reg(); | 411 Register left2 = left_pair->At(1).reg(); |
410 __ movaps(XMM0, left); | 412 PairLocation* right_pair = locs.in(1).AsPairLocation(); |
411 __ pcmpeqq(XMM0, right); | 413 Register right1 = right_pair->At(0).reg(); |
412 __ movd(temp, XMM0); | 414 Register right2 = right_pair->At(1).reg(); |
413 | 415 Label done; |
416 // Compare lower. | |
417 __ cmpl(left1, right1); | |
418 __ j(NOT_EQUAL, &done); | |
419 // Lower is equal, compare upper. | |
420 __ cmpl(left2, right2); | |
421 __ Bind(&done); | |
414 Condition true_condition = TokenKindToMintCondition(kind); | 422 Condition true_condition = TokenKindToMintCondition(kind); |
415 __ cmpl(temp, Immediate(-1)); | |
416 return true_condition; | 423 return true_condition; |
417 } | 424 } |
418 | 425 |
419 | 426 |
420 static Condition EmitUnboxedMintComparisonOp(FlowGraphCompiler* compiler, | 427 static Condition EmitUnboxedMintComparisonOp(FlowGraphCompiler* compiler, |
421 const LocationSummary& locs, | 428 const LocationSummary& locs, |
422 Token::Kind kind, | 429 Token::Kind kind, |
423 BranchLabels labels) { | 430 BranchLabels labels) { |
424 XmmRegister left = locs.in(0).fpu_reg(); | 431 PairLocation* left_pair = locs.in(0).AsPairLocation(); |
425 XmmRegister right = locs.in(1).fpu_reg(); | 432 Register left1 = left_pair->At(0).reg(); |
426 Register left_tmp = locs.temp(0).reg(); | 433 Register left2 = left_pair->At(1).reg(); |
427 Register right_tmp = locs.temp(1).reg(); | 434 PairLocation* right_pair = locs.in(1).AsPairLocation(); |
435 Register right1 = right_pair->At(0).reg(); | |
436 Register right2 = right_pair->At(1).reg(); | |
428 | 437 |
429 Condition hi_cond = OVERFLOW, lo_cond = OVERFLOW; | 438 Condition hi_cond = OVERFLOW, lo_cond = OVERFLOW; |
430 switch (kind) { | 439 switch (kind) { |
431 case Token::kLT: | 440 case Token::kLT: |
432 hi_cond = LESS; | 441 hi_cond = LESS; |
433 lo_cond = BELOW; | 442 lo_cond = BELOW; |
434 break; | 443 break; |
435 case Token::kGT: | 444 case Token::kGT: |
436 hi_cond = GREATER; | 445 hi_cond = GREATER; |
437 lo_cond = ABOVE; | 446 lo_cond = ABOVE; |
438 break; | 447 break; |
439 case Token::kLTE: | 448 case Token::kLTE: |
440 hi_cond = LESS; | 449 hi_cond = LESS; |
441 lo_cond = BELOW_EQUAL; | 450 lo_cond = BELOW_EQUAL; |
442 break; | 451 break; |
443 case Token::kGTE: | 452 case Token::kGTE: |
444 hi_cond = GREATER; | 453 hi_cond = GREATER; |
445 lo_cond = ABOVE_EQUAL; | 454 lo_cond = ABOVE_EQUAL; |
446 break; | 455 break; |
447 default: | 456 default: |
448 break; | 457 break; |
449 } | 458 } |
450 ASSERT(hi_cond != OVERFLOW && lo_cond != OVERFLOW); | 459 ASSERT(hi_cond != OVERFLOW && lo_cond != OVERFLOW); |
451 Label is_true, is_false; | 460 Label is_true, is_false; |
452 // Compare upper halves first. | 461 // Compare upper halves first. |
453 __ pextrd(left_tmp, left, Immediate(1)); | 462 __ cmpl(left2, right2); |
454 __ pextrd(right_tmp, right, Immediate(1)); | |
455 __ cmpl(left_tmp, right_tmp); | |
456 __ j(hi_cond, labels.true_label); | 463 __ j(hi_cond, labels.true_label); |
457 __ j(FlipCondition(hi_cond), labels.false_label); | 464 __ j(FlipCondition(hi_cond), labels.false_label); |
458 | 465 |
459 // If upper is equal, compare lower half. | 466 // If upper is equal, compare lower half. |
460 __ pextrd(left_tmp, left, Immediate(0)); | 467 __ cmpl(left1, right1); |
461 __ pextrd(right_tmp, right, Immediate(0)); | |
462 __ cmpl(left_tmp, right_tmp); | |
463 return lo_cond; | 468 return lo_cond; |
464 } | 469 } |
465 | 470 |
466 | 471 |
467 static Condition TokenKindToDoubleCondition(Token::Kind kind) { | 472 static Condition TokenKindToDoubleCondition(Token::Kind kind) { |
468 switch (kind) { | 473 switch (kind) { |
469 case Token::kEQ: return EQUAL; | 474 case Token::kEQ: return EQUAL; |
470 case Token::kNE: return NOT_EQUAL; | 475 case Token::kNE: return NOT_EQUAL; |
471 case Token::kLT: return BELOW; | 476 case Token::kLT: return BELOW; |
472 case Token::kGT: return ABOVE; | 477 case Token::kGT: return ABOVE; |
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
651 __ Bind(&is_true); | 656 __ Bind(&is_true); |
652 __ LoadObject(result_reg, Bool::True()); | 657 __ LoadObject(result_reg, Bool::True()); |
653 __ Bind(&done); | 658 __ Bind(&done); |
654 } | 659 } |
655 | 660 |
656 | 661 |
657 LocationSummary* RelationalOpInstr::MakeLocationSummary(bool opt) const { | 662 LocationSummary* RelationalOpInstr::MakeLocationSummary(bool opt) const { |
658 const intptr_t kNumInputs = 2; | 663 const intptr_t kNumInputs = 2; |
659 const intptr_t kNumTemps = 0; | 664 const intptr_t kNumTemps = 0; |
660 if (operation_cid() == kMintCid) { | 665 if (operation_cid() == kMintCid) { |
661 const intptr_t kNumTemps = 2; | 666 const intptr_t kNumTemps = 0; |
662 LocationSummary* locs = | 667 LocationSummary* locs = |
663 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 668 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
664 locs->set_in(0, Location::RequiresFpuRegister()); | 669 locs->set_in(0, Location::Pair(Location::RequiresRegister(), |
665 locs->set_in(1, Location::RequiresFpuRegister()); | 670 Location::RequiresRegister())); |
666 locs->set_temp(0, Location::RequiresRegister()); | 671 locs->set_in(1, Location::Pair(Location::RequiresRegister(), |
667 locs->set_temp(1, Location::RequiresRegister()); | 672 Location::RequiresRegister())); |
668 locs->set_out(0, Location::RequiresRegister()); | 673 locs->set_out(0, Location::RequiresRegister()); |
669 return locs; | 674 return locs; |
670 } | 675 } |
671 if (operation_cid() == kDoubleCid) { | 676 if (operation_cid() == kDoubleCid) { |
672 LocationSummary* summary = | 677 LocationSummary* summary = |
673 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 678 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
674 summary->set_in(0, Location::RequiresFpuRegister()); | 679 summary->set_in(0, Location::RequiresFpuRegister()); |
675 summary->set_in(1, Location::RequiresFpuRegister()); | 680 summary->set_in(1, Location::RequiresFpuRegister()); |
676 summary->set_out(0, Location::RequiresRegister()); | 681 summary->set_out(0, Location::RequiresRegister()); |
677 return summary; | 682 return summary; |
(...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
983 // element sizes > 1). | 988 // element sizes > 1). |
984 locs->set_in(1, (index_scale() == 1) | 989 locs->set_in(1, (index_scale() == 1) |
985 ? Location::WritableRegister() | 990 ? Location::WritableRegister() |
986 : Location::RequiresRegister()); | 991 : Location::RequiresRegister()); |
987 } | 992 } |
988 if ((representation() == kUnboxedDouble) || | 993 if ((representation() == kUnboxedDouble) || |
989 (representation() == kUnboxedFloat32x4) || | 994 (representation() == kUnboxedFloat32x4) || |
990 (representation() == kUnboxedInt32x4) || | 995 (representation() == kUnboxedInt32x4) || |
991 (representation() == kUnboxedFloat64x2)) { | 996 (representation() == kUnboxedFloat64x2)) { |
992 locs->set_out(0, Location::RequiresFpuRegister()); | 997 locs->set_out(0, Location::RequiresFpuRegister()); |
998 } else if (representation() == kUnboxedMint) { | |
999 locs->set_out(0, Location::Pair(Location::RegisterLocation(EAX), | |
1000 Location::RegisterLocation(EDX))); | |
993 } else { | 1001 } else { |
1002 ASSERT(representation() == kTagged); | |
994 locs->set_out(0, Location::RequiresRegister()); | 1003 locs->set_out(0, Location::RequiresRegister()); |
995 } | 1004 } |
996 return locs; | 1005 return locs; |
997 } | 1006 } |
998 | 1007 |
999 | 1008 |
1000 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1009 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
1001 Register array = locs()->in(0).reg(); | 1010 Register array = locs()->in(0).reg(); |
1002 Location index = locs()->in(1); | 1011 Location index = locs()->in(1); |
1003 | 1012 |
1004 Address element_address(kNoRegister, 0); | 1013 Address element_address(kNoRegister, 0); |
1005 if (IsExternal()) { | 1014 if (IsExternal()) { |
1006 element_address = index.IsRegister() | 1015 element_address = index.IsRegister() |
1007 ? FlowGraphCompiler::ExternalElementAddressForRegIndex( | 1016 ? FlowGraphCompiler::ExternalElementAddressForRegIndex( |
1008 index_scale(), array, index.reg()) | 1017 index_scale(), array, index.reg()) |
1009 : FlowGraphCompiler::ExternalElementAddressForIntIndex( | 1018 : FlowGraphCompiler::ExternalElementAddressForIntIndex( |
1010 index_scale(), array, Smi::Cast(index.constant()).Value()); | 1019 index_scale(), array, Smi::Cast(index.constant()).Value()); |
1011 } else { | 1020 } else { |
1012 ASSERT(this->array()->definition()->representation() == kTagged); | 1021 ASSERT(this->array()->definition()->representation() == kTagged); |
1013 element_address = index.IsRegister() | 1022 element_address = index.IsRegister() |
1014 ? FlowGraphCompiler::ElementAddressForRegIndex( | 1023 ? FlowGraphCompiler::ElementAddressForRegIndex( |
1015 class_id(), index_scale(), array, index.reg()) | 1024 class_id(), index_scale(), array, index.reg()) |
1016 : FlowGraphCompiler::ElementAddressForIntIndex( | 1025 : FlowGraphCompiler::ElementAddressForIntIndex( |
1017 class_id(), index_scale(), array, | 1026 class_id(), index_scale(), array, |
1018 Smi::Cast(index.constant()).Value()); | 1027 Smi::Cast(index.constant()).Value()); |
1019 } | 1028 } |
1020 | 1029 |
1021 if ((representation() == kUnboxedDouble) || | 1030 if ((representation() == kUnboxedDouble) || |
1022 (representation() == kUnboxedMint) || | |
1023 (representation() == kUnboxedFloat32x4) || | 1031 (representation() == kUnboxedFloat32x4) || |
1024 (representation() == kUnboxedInt32x4) || | 1032 (representation() == kUnboxedInt32x4) || |
1025 (representation() == kUnboxedFloat64x2)) { | 1033 (representation() == kUnboxedFloat64x2)) { |
1026 XmmRegister result = locs()->out(0).fpu_reg(); | 1034 XmmRegister result = locs()->out(0).fpu_reg(); |
1027 if ((index_scale() == 1) && index.IsRegister()) { | 1035 if ((index_scale() == 1) && index.IsRegister()) { |
1028 __ SmiUntag(index.reg()); | 1036 __ SmiUntag(index.reg()); |
1029 } | 1037 } |
1030 switch (class_id()) { | 1038 switch (class_id()) { |
1031 case kTypedDataInt32ArrayCid: | |
1032 __ movss(result, element_address); | |
1033 __ pmovsxdq(result, result); | |
1034 break; | |
1035 case kTypedDataUint32ArrayCid: | |
1036 __ xorpd(result, result); | |
1037 __ movss(result, element_address); | |
1038 break; | |
1039 case kTypedDataFloat32ArrayCid: | 1039 case kTypedDataFloat32ArrayCid: |
1040 __ movss(result, element_address); | 1040 __ movss(result, element_address); |
1041 break; | 1041 break; |
1042 case kTypedDataFloat64ArrayCid: | 1042 case kTypedDataFloat64ArrayCid: |
1043 __ movsd(result, element_address); | 1043 __ movsd(result, element_address); |
1044 break; | 1044 break; |
1045 case kTypedDataInt32x4ArrayCid: | 1045 case kTypedDataInt32x4ArrayCid: |
1046 case kTypedDataFloat32x4ArrayCid: | 1046 case kTypedDataFloat32x4ArrayCid: |
1047 case kTypedDataFloat64x2ArrayCid: | 1047 case kTypedDataFloat64x2ArrayCid: |
1048 __ movups(result, element_address); | 1048 __ movups(result, element_address); |
1049 break; | 1049 break; |
1050 default: | |
1051 UNREACHABLE(); | |
1050 } | 1052 } |
1051 return; | 1053 return; |
1052 } | 1054 } |
1053 | 1055 |
1056 if (representation() == kUnboxedMint) { | |
1057 ASSERT(locs()->out(0).IsPairLocation()); | |
1058 PairLocation* result_pair = locs()->out(0).AsPairLocation(); | |
1059 Register result1 = result_pair->At(0).reg(); | |
1060 Register result2 = result_pair->At(1).reg(); | |
1061 ASSERT(result1 == EAX); | |
1062 ASSERT(result2 == EDX); | |
1063 if ((index_scale() == 1) && index.IsRegister()) { | |
1064 __ SmiUntag(index.reg()); | |
1065 } | |
1066 switch (class_id()) { | |
1067 case kTypedDataInt32ArrayCid: | |
1068 __ movl(result1, element_address); | |
1069 __ cdq(); | |
1070 break; | |
1071 case kTypedDataUint32ArrayCid: | |
1072 __ movl(result1, element_address); | |
1073 __ xorl(result2, result2); | |
1074 break; | |
1075 default: | |
1076 UNREACHABLE(); | |
1077 } | |
1078 return; | |
1079 } | |
1080 | |
1081 ASSERT(representation() == kTagged); | |
1082 | |
1054 Register result = locs()->out(0).reg(); | 1083 Register result = locs()->out(0).reg(); |
1055 if ((index_scale() == 1) && index.IsRegister()) { | 1084 if ((index_scale() == 1) && index.IsRegister()) { |
1056 __ SmiUntag(index.reg()); | 1085 __ SmiUntag(index.reg()); |
1057 } | 1086 } |
1058 switch (class_id()) { | 1087 switch (class_id()) { |
1059 case kTypedDataInt8ArrayCid: | 1088 case kTypedDataInt8ArrayCid: |
1060 ASSERT(index_scale() == 1); | 1089 ASSERT(index_scale() == 1); |
1061 __ movsxb(result, element_address); | 1090 __ movsxb(result, element_address); |
1062 __ SmiTag(result); | 1091 __ SmiTag(result); |
1063 break; | 1092 break; |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1175 // EBX, ECX, EDX) instead of using a fixed register. | 1204 // EBX, ECX, EDX) instead of using a fixed register. |
1176 locs->set_in(2, Location::FixedRegisterOrSmiConstant(value(), EAX)); | 1205 locs->set_in(2, Location::FixedRegisterOrSmiConstant(value(), EAX)); |
1177 break; | 1206 break; |
1178 case kTypedDataInt16ArrayCid: | 1207 case kTypedDataInt16ArrayCid: |
1179 case kTypedDataUint16ArrayCid: | 1208 case kTypedDataUint16ArrayCid: |
1180 // Writable register because the value must be untagged before storing. | 1209 // Writable register because the value must be untagged before storing. |
1181 locs->set_in(2, Location::WritableRegister()); | 1210 locs->set_in(2, Location::WritableRegister()); |
1182 break; | 1211 break; |
1183 case kTypedDataInt32ArrayCid: | 1212 case kTypedDataInt32ArrayCid: |
1184 case kTypedDataUint32ArrayCid: | 1213 case kTypedDataUint32ArrayCid: |
1185 // Mints are stored in XMM registers. For smis, use a writable register | 1214 // For smis, use a writable register because the value must be untagged |
1186 // because the value must be untagged before storing. | 1215 // before storing. Mints are stored in registers pairs. |
1187 locs->set_in(2, value()->IsSmiValue() | 1216 if (value()->IsSmiValue()) { |
1188 ? Location::WritableRegister() | 1217 locs->set_in(2, Location::WritableRegister()); |
1189 : Location::RequiresFpuRegister()); | 1218 } else { |
1219 // We only move the lower 32-bits so we don't care where the high bits | |
1220 // are located. | |
1221 locs->set_in(2, Location::Pair(Location::RequiresRegister(), | |
1222 Location::Any())); | |
1223 } | |
1190 break; | 1224 break; |
1191 case kTypedDataFloat32ArrayCid: | 1225 case kTypedDataFloat32ArrayCid: |
1192 case kTypedDataFloat64ArrayCid: | 1226 case kTypedDataFloat64ArrayCid: |
1193 // TODO(srdjan): Support Float64 constants. | 1227 // TODO(srdjan): Support Float64 constants. |
1194 locs->set_in(2, Location::RequiresFpuRegister()); | 1228 locs->set_in(2, Location::RequiresFpuRegister()); |
1195 break; | 1229 break; |
1196 case kTypedDataInt32x4ArrayCid: | 1230 case kTypedDataInt32x4ArrayCid: |
1197 case kTypedDataFloat32x4ArrayCid: | 1231 case kTypedDataFloat32x4ArrayCid: |
1198 case kTypedDataFloat64x2ArrayCid: | 1232 case kTypedDataFloat64x2ArrayCid: |
1199 locs->set_in(2, Location::RequiresFpuRegister()); | 1233 locs->set_in(2, Location::RequiresFpuRegister()); |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1296 } | 1330 } |
1297 case kTypedDataInt32ArrayCid: | 1331 case kTypedDataInt32ArrayCid: |
1298 case kTypedDataUint32ArrayCid: | 1332 case kTypedDataUint32ArrayCid: |
1299 if (value()->IsSmiValue()) { | 1333 if (value()->IsSmiValue()) { |
1300 ASSERT(RequiredInputRepresentation(2) == kTagged); | 1334 ASSERT(RequiredInputRepresentation(2) == kTagged); |
1301 Register value = locs()->in(2).reg(); | 1335 Register value = locs()->in(2).reg(); |
1302 __ SmiUntag(value); | 1336 __ SmiUntag(value); |
1303 __ movl(element_address, value); | 1337 __ movl(element_address, value); |
1304 } else { | 1338 } else { |
1305 ASSERT(RequiredInputRepresentation(2) == kUnboxedMint); | 1339 ASSERT(RequiredInputRepresentation(2) == kUnboxedMint); |
1306 __ movss(element_address, locs()->in(2).fpu_reg()); | 1340 PairLocation* value_pair = locs()->in(2).AsPairLocation(); |
1341 Register value1 = value_pair->At(0).reg(); | |
1342 __ movl(element_address, value1); | |
1307 } | 1343 } |
1308 break; | 1344 break; |
1309 case kTypedDataFloat32ArrayCid: | 1345 case kTypedDataFloat32ArrayCid: |
1310 __ movss(element_address, locs()->in(2).fpu_reg()); | 1346 __ movss(element_address, locs()->in(2).fpu_reg()); |
1311 break; | 1347 break; |
1312 case kTypedDataFloat64ArrayCid: | 1348 case kTypedDataFloat64ArrayCid: |
1313 __ movsd(element_address, locs()->in(2).fpu_reg()); | 1349 __ movsd(element_address, locs()->in(2).fpu_reg()); |
1314 break; | 1350 break; |
1315 case kTypedDataInt32x4ArrayCid: | 1351 case kTypedDataInt32x4ArrayCid: |
1316 case kTypedDataFloat32x4ArrayCid: | 1352 case kTypedDataFloat32x4ArrayCid: |
(...skipping 4002 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5319 Register length = length_loc.reg(); | 5355 Register length = length_loc.reg(); |
5320 Register index = index_loc.reg(); | 5356 Register index = index_loc.reg(); |
5321 __ cmpl(index, length); | 5357 __ cmpl(index, length); |
5322 __ j(ABOVE_EQUAL, deopt); | 5358 __ j(ABOVE_EQUAL, deopt); |
5323 } | 5359 } |
5324 } | 5360 } |
5325 | 5361 |
5326 | 5362 |
5327 LocationSummary* UnboxIntegerInstr::MakeLocationSummary(bool opt) const { | 5363 LocationSummary* UnboxIntegerInstr::MakeLocationSummary(bool opt) const { |
5328 const intptr_t kNumInputs = 1; | 5364 const intptr_t kNumInputs = 1; |
5329 const intptr_t value_cid = value()->Type()->ToCid(); | 5365 const intptr_t kNumTemps = 0; |
5330 const bool needs_temp = ((value_cid != kSmiCid) && (value_cid != kMintCid)); | |
5331 const bool needs_writable_input = (value_cid == kSmiCid); | |
5332 const intptr_t kNumTemps = needs_temp ? 1 : 0; | |
5333 LocationSummary* summary = | 5366 LocationSummary* summary = |
5334 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5367 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5335 summary->set_in(0, needs_writable_input | 5368 summary->set_in(0, Location::RequiresRegister()); |
5336 ? Location::WritableRegister() | 5369 summary->set_out(0, Location::Pair(Location::RegisterLocation(EAX), |
5337 : Location::RequiresRegister()); | 5370 Location::RegisterLocation(EDX))); |
5338 if (needs_temp) { | |
5339 summary->set_temp(0, Location::RequiresRegister()); | |
5340 } | |
5341 summary->set_out(0, Location::RequiresFpuRegister()); | |
5342 return summary; | 5371 return summary; |
5343 } | 5372 } |
5344 | 5373 |
5345 | 5374 |
5346 void UnboxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5375 void UnboxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5347 const intptr_t value_cid = value()->Type()->ToCid(); | 5376 const intptr_t value_cid = value()->Type()->ToCid(); |
5348 const Register value = locs()->in(0).reg(); | 5377 const Register value = locs()->in(0).reg(); |
5349 const XmmRegister result = locs()->out(0).fpu_reg(); | 5378 PairLocation* result_pair = locs()->out(0).AsPairLocation(); |
5379 Register result1 = result_pair->At(0).reg(); | |
5380 Register result2 = result_pair->At(1).reg(); | |
5381 | |
5382 ASSERT(value != result1); | |
5383 ASSERT(value != result2); | |
5384 ASSERT(result1 == EAX); | |
5385 ASSERT(result2 == EDX); | |
5350 | 5386 |
5351 if (value_cid == kMintCid) { | 5387 if (value_cid == kMintCid) { |
5352 __ movsd(result, FieldAddress(value, Mint::value_offset())); | 5388 __ movl(result1, FieldAddress(value, Mint::value_offset())); |
5389 __ movl(result2, FieldAddress(value, Mint::value_offset() + kWordSize)); | |
5353 } else if (value_cid == kSmiCid) { | 5390 } else if (value_cid == kSmiCid) { |
5354 __ SmiUntag(value); // Untag input before conversion. | 5391 __ movl(result1, value); |
5355 __ movd(result, value); | 5392 __ SmiUntag(result1); |
5356 __ pmovsxdq(result, result); | 5393 // Sign extend into result2. |
5394 __ cdq(); | |
5357 } else { | 5395 } else { |
5358 Register temp = locs()->temp(0).reg(); | |
5359 Label* deopt = compiler->AddDeoptStub(deopt_id_, | 5396 Label* deopt = compiler->AddDeoptStub(deopt_id_, |
5360 ICData::kDeoptUnboxInteger); | 5397 ICData::kDeoptUnboxInteger); |
5361 Label is_smi, done; | 5398 Label is_smi, done; |
5362 __ testl(value, Immediate(kSmiTagMask)); | 5399 __ testl(value, Immediate(kSmiTagMask)); |
5363 __ j(ZERO, &is_smi); | 5400 __ j(ZERO, &is_smi); |
5364 __ CompareClassId(value, kMintCid, temp); | 5401 __ CompareClassId(value, kMintCid, result1); |
5365 __ j(NOT_EQUAL, deopt); | 5402 __ j(NOT_EQUAL, deopt); |
5366 __ movsd(result, FieldAddress(value, Mint::value_offset())); | 5403 __ movl(result1, FieldAddress(value, Mint::value_offset())); |
5404 __ movl(result2, FieldAddress(value, Mint::value_offset() + kWordSize)); | |
5367 __ jmp(&done); | 5405 __ jmp(&done); |
5368 __ Bind(&is_smi); | 5406 __ Bind(&is_smi); |
5369 __ movl(temp, value); | 5407 __ movl(result1, value); |
5370 __ SmiUntag(temp); | 5408 __ SmiUntag(result1); |
5371 __ movd(result, temp); | 5409 // Sign extend into result2. |
5372 __ pmovsxdq(result, result); | 5410 __ cdq(); |
5373 __ Bind(&done); | 5411 __ Bind(&done); |
5374 } | 5412 } |
5375 } | 5413 } |
5376 | 5414 |
5377 | 5415 |
5378 LocationSummary* BoxIntegerInstr::MakeLocationSummary(bool opt) const { | 5416 LocationSummary* BoxIntegerInstr::MakeLocationSummary(bool opt) const { |
5379 const intptr_t kNumInputs = 1; | 5417 const intptr_t kNumInputs = 1; |
5380 const intptr_t kNumTemps = 2; | 5418 const intptr_t kNumTemps = 1; |
5381 LocationSummary* summary = | 5419 LocationSummary* summary = |
5382 new LocationSummary(kNumInputs, | 5420 new LocationSummary(kNumInputs, |
5383 kNumTemps, | 5421 kNumTemps, |
5384 LocationSummary::kCallOnSlowPath); | 5422 LocationSummary::kCallOnSlowPath); |
5385 summary->set_in(0, Location::RequiresFpuRegister()); | 5423 summary->set_in(0, Location::Pair(Location::RegisterLocation(EAX), |
5386 summary->set_temp(0, Location::RegisterLocation(EAX)); | 5424 Location::RegisterLocation(EDX))); |
5387 summary->set_temp(1, Location::RegisterLocation(EDX)); | 5425 summary->set_temp(0, Location::RequiresRegister()); |
5388 // TODO(fschneider): Save one temp by using result register as a temp. | |
5389 summary->set_out(0, Location::RequiresRegister()); | 5426 summary->set_out(0, Location::RequiresRegister()); |
5390 return summary; | 5427 return summary; |
5391 } | 5428 } |
5392 | 5429 |
5393 | 5430 |
5394 class BoxIntegerSlowPath : public SlowPathCode { | 5431 class BoxIntegerSlowPath : public SlowPathCode { |
5395 public: | 5432 public: |
5396 explicit BoxIntegerSlowPath(BoxIntegerInstr* instruction) | 5433 explicit BoxIntegerSlowPath(BoxIntegerInstr* instruction) |
5397 : instruction_(instruction) { } | 5434 : instruction_(instruction) { } |
5398 | 5435 |
(...skipping 21 matching lines...) Expand all Loading... | |
5420 } | 5457 } |
5421 | 5458 |
5422 private: | 5459 private: |
5423 BoxIntegerInstr* instruction_; | 5460 BoxIntegerInstr* instruction_; |
5424 }; | 5461 }; |
5425 | 5462 |
5426 | 5463 |
5427 void BoxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5464 void BoxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5428 BoxIntegerSlowPath* slow_path = new BoxIntegerSlowPath(this); | 5465 BoxIntegerSlowPath* slow_path = new BoxIntegerSlowPath(this); |
5429 compiler->AddSlowPathCode(slow_path); | 5466 compiler->AddSlowPathCode(slow_path); |
5467 PairLocation* value_pair = locs()->in(0).AsPairLocation(); | |
5468 Register value1 = value_pair->At(0).reg(); | |
5469 Register value2 = value_pair->At(1).reg(); | |
5470 Register out_reg = locs()->out(0).reg(); | |
5430 | 5471 |
5431 Register out_reg = locs()->out(0).reg(); | 5472 ASSERT(value1 == EAX); |
5432 XmmRegister value = locs()->in(0).fpu_reg(); | 5473 ASSERT(value2 == EDX); |
5474 | |
5475 // Copy value2 into out_reg as a temporary. | |
5476 // We modify value1 but restore it before using it. | |
5477 __ movl(out_reg, value2); | |
5433 | 5478 |
5434 // Unboxed operations produce smis or mint-sized values. | 5479 // Unboxed operations produce smis or mint-sized values. |
5435 // Check if value fits into a smi. | 5480 // Check if value fits into a smi. |
5436 Label not_smi, done; | 5481 Label not_smi, done; |
5437 __ pextrd(EDX, value, Immediate(1)); // Upper half. | 5482 |
5438 __ pextrd(EAX, value, Immediate(0)); // Lower half. | |
5439 // 1. Compute (x + -kMinSmi) which has to be in the range | 5483 // 1. Compute (x + -kMinSmi) which has to be in the range |
5440 // 0 .. -kMinSmi+kMaxSmi for x to fit into a smi. | 5484 // 0 .. -kMinSmi+kMaxSmi for x to fit into a smi. |
5441 __ addl(EAX, Immediate(0x40000000)); | 5485 __ addl(value1, Immediate(0x40000000)); |
5442 __ adcl(EDX, Immediate(0)); | 5486 __ adcl(out_reg, Immediate(0)); |
5443 // 2. Unsigned compare to -kMinSmi+kMaxSmi. | 5487 // 2. Unsigned compare to -kMinSmi+kMaxSmi. |
5444 __ cmpl(EAX, Immediate(0x80000000)); | 5488 __ cmpl(value1, Immediate(0x80000000)); |
5445 __ sbbl(EDX, Immediate(0)); | 5489 __ sbbl(out_reg, Immediate(0)); |
5446 __ j(ABOVE_EQUAL, ¬_smi); | 5490 __ j(ABOVE_EQUAL, ¬_smi); |
5447 // 3. Restore lower half if result is a smi. | 5491 // 3. Restore lower half if result is a smi. |
5448 __ subl(EAX, Immediate(0x40000000)); | 5492 __ subl(value1, Immediate(0x40000000)); |
5449 | 5493 __ movl(out_reg, value1); |
5450 __ SmiTag(EAX); | 5494 __ SmiTag(out_reg); |
5451 __ movl(out_reg, EAX); | |
5452 __ jmp(&done); | 5495 __ jmp(&done); |
5453 | |
5454 __ Bind(¬_smi); | 5496 __ Bind(¬_smi); |
5455 __ TryAllocate( | 5497 __ TryAllocate( |
5456 Class::ZoneHandle(Isolate::Current()->object_store()->mint_class()), | 5498 Class::ZoneHandle(Isolate::Current()->object_store()->mint_class()), |
5457 slow_path->entry_label(), | 5499 slow_path->entry_label(), |
5458 Assembler::kFarJump, | 5500 Assembler::kFarJump, |
5459 out_reg, | 5501 out_reg, |
5460 kNoRegister); | 5502 kNoRegister); |
5461 __ Bind(slow_path->exit_label()); | 5503 __ Bind(slow_path->exit_label()); |
5462 __ movsd(FieldAddress(out_reg, Mint::value_offset()), value); | 5504 // 3. Restore lower half of input before using it. |
5505 __ subl(value1, Immediate(0x40000000)); | |
5506 __ movl(FieldAddress(out_reg, Mint::value_offset()), value1); | |
5507 __ movl(FieldAddress(out_reg, Mint::value_offset() + kWordSize), value2); | |
5463 __ Bind(&done); | 5508 __ Bind(&done); |
5464 } | 5509 } |
5465 | 5510 |
5466 | 5511 |
5467 LocationSummary* BinaryMintOpInstr::MakeLocationSummary(bool opt) const { | 5512 LocationSummary* BinaryMintOpInstr::MakeLocationSummary(bool opt) const { |
5468 const intptr_t kNumInputs = 2; | 5513 const intptr_t kNumInputs = 2; |
5469 switch (op_kind()) { | 5514 switch (op_kind()) { |
5470 case Token::kBIT_AND: | 5515 case Token::kBIT_AND: |
5471 case Token::kBIT_OR: | 5516 case Token::kBIT_OR: |
5472 case Token::kBIT_XOR: { | 5517 case Token::kBIT_XOR: { |
5473 const intptr_t kNumTemps = | 5518 const intptr_t kNumTemps = FLAG_throw_on_javascript_int_overflow ? 1 : 0; |
5474 FLAG_throw_on_javascript_int_overflow ? 1 : 0; | |
5475 LocationSummary* summary = | 5519 LocationSummary* summary = |
5476 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5520 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5477 summary->set_in(0, Location::RequiresFpuRegister()); | 5521 summary->set_in(0, Location::Pair(Location::RequiresRegister(), |
5478 summary->set_in(1, Location::RequiresFpuRegister()); | 5522 Location::RequiresRegister())); |
5523 summary->set_in(1, Location::Pair(Location::RequiresRegister(), | |
5524 Location::RequiresRegister())); | |
5479 if (FLAG_throw_on_javascript_int_overflow) { | 5525 if (FLAG_throw_on_javascript_int_overflow) { |
5480 summary->set_temp(0, Location::RequiresRegister()); | 5526 summary->set_temp(0, Location::RequiresRegister()); |
5481 } | 5527 } |
5482 summary->set_out(0, Location::SameAsFirstInput()); | 5528 summary->set_out(0, Location::SameAsFirstInput()); |
5483 return summary; | 5529 return summary; |
5484 } | 5530 } |
5485 case Token::kADD: | 5531 case Token::kADD: |
5486 case Token::kSUB: { | 5532 case Token::kSUB: { |
5487 const intptr_t kNumTemps = 2; | 5533 const intptr_t kNumTemps = FLAG_throw_on_javascript_int_overflow ? 1 : 0; |
5488 LocationSummary* summary = | 5534 LocationSummary* summary = |
5489 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5535 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5490 summary->set_in(0, Location::RequiresFpuRegister()); | 5536 summary->set_in(0, Location::Pair(Location::RequiresRegister(), |
5491 summary->set_in(1, Location::RequiresFpuRegister()); | 5537 Location::RequiresRegister())); |
5492 summary->set_temp(0, Location::RequiresRegister()); | 5538 summary->set_in(1, Location::Pair(Location::RequiresRegister(), |
5493 summary->set_temp(1, Location::RequiresRegister()); | 5539 Location::RequiresRegister())); |
5494 summary->set_out(0, Location::SameAsFirstInput()); | 5540 summary->set_out(0, Location::SameAsFirstInput()); |
5541 if (FLAG_throw_on_javascript_int_overflow) { | |
5542 summary->set_temp(0, Location::RequiresRegister()); | |
Florian Schneider
2014/04/30 18:55:46
A temp may not be needed anymore with your new cod
Cutch
2014/05/14 17:16:19
Done.
| |
5543 } | |
5495 return summary; | 5544 return summary; |
5496 } | 5545 } |
5497 default: | 5546 default: |
5498 UNREACHABLE(); | 5547 UNREACHABLE(); |
5499 return NULL; | 5548 return NULL; |
5500 } | 5549 } |
5501 } | 5550 } |
5502 | 5551 |
5503 | 5552 |
5504 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5553 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5505 XmmRegister left = locs()->in(0).fpu_reg(); | 5554 PairLocation* left_pair = locs()->in(0).AsPairLocation(); |
5506 XmmRegister right = locs()->in(1).fpu_reg(); | 5555 Register left1 = left_pair->At(0).reg(); |
5507 | 5556 Register left2 = left_pair->At(1).reg(); |
5508 ASSERT(locs()->out(0).fpu_reg() == left); | 5557 PairLocation* right_pair = locs()->in(1).AsPairLocation(); |
5558 Register right1 = right_pair->At(0).reg(); | |
5559 Register right2 = right_pair->At(1).reg(); | |
5560 PairLocation* out_pair = locs()->out(0).AsPairLocation(); | |
5561 Register out1 = out_pair->At(0).reg(); | |
5562 Register out2 = out_pair->At(1).reg(); | |
5563 ASSERT(out1 == left1); | |
5564 ASSERT(out2 == left2); | |
5509 | 5565 |
5510 Label* deopt = NULL; | 5566 Label* deopt = NULL; |
5511 if (FLAG_throw_on_javascript_int_overflow) { | 5567 if (FLAG_throw_on_javascript_int_overflow) { |
5512 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp); | 5568 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp); |
5513 } | 5569 } |
5514 switch (op_kind()) { | 5570 switch (op_kind()) { |
5515 case Token::kBIT_AND: __ andpd(left, right); break; | 5571 case Token::kBIT_AND: |
5516 case Token::kBIT_OR: __ orpd(left, right); break; | 5572 __ andl(left1, right1); |
5517 case Token::kBIT_XOR: __ xorpd(left, right); break; | 5573 __ andl(left2, right2); |
5574 break; | |
5575 case Token::kBIT_OR: | |
5576 __ orl(left1, right1); | |
5577 __ orl(left2, right2); | |
5578 break; | |
5579 case Token::kBIT_XOR: | |
5580 __ xorl(left1, right1); | |
5581 __ xorl(left2, right2); | |
5582 break; | |
5518 case Token::kADD: | 5583 case Token::kADD: |
5519 case Token::kSUB: { | 5584 case Token::kSUB: { |
5520 Register lo = locs()->temp(0).reg(); | |
5521 Register hi = locs()->temp(1).reg(); | |
5522 if (!FLAG_throw_on_javascript_int_overflow) { | 5585 if (!FLAG_throw_on_javascript_int_overflow) { |
5523 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp); | 5586 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp); |
5524 } | 5587 } |
5525 | |
5526 Label done, overflow; | |
5527 __ pextrd(lo, right, Immediate(0)); // Lower half | |
5528 __ pextrd(hi, right, Immediate(1)); // Upper half | |
5529 __ subl(ESP, Immediate(2 * kWordSize)); | |
5530 __ movq(Address(ESP, 0), left); | |
5531 if (op_kind() == Token::kADD) { | 5588 if (op_kind() == Token::kADD) { |
5532 __ addl(Address(ESP, 0), lo); | 5589 __ addl(left1, right1); |
5533 __ adcl(Address(ESP, 1 * kWordSize), hi); | 5590 __ adcl(left2, right2); |
5534 } else { | 5591 } else { |
5535 __ subl(Address(ESP, 0), lo); | 5592 __ subl(left1, right1); |
5536 __ sbbl(Address(ESP, 1 * kWordSize), hi); | 5593 __ sbbl(left2, right2); |
5537 } | 5594 } |
5538 __ j(OVERFLOW, &overflow); | 5595 __ j(OVERFLOW, deopt); |
5539 __ movq(left, Address(ESP, 0)); | |
5540 __ addl(ESP, Immediate(2 * kWordSize)); | |
5541 __ jmp(&done); | |
5542 __ Bind(&overflow); | |
5543 __ addl(ESP, Immediate(2 * kWordSize)); | |
5544 __ jmp(deopt); | |
5545 __ Bind(&done); | |
5546 break; | 5596 break; |
5547 } | 5597 } |
5548 default: UNREACHABLE(); | 5598 default: UNREACHABLE(); |
5549 } | 5599 } |
5550 if (FLAG_throw_on_javascript_int_overflow) { | 5600 if (FLAG_throw_on_javascript_int_overflow) { |
5551 Register tmp = locs()->temp(0).reg(); | 5601 Register tmp = locs()->temp(0).reg(); |
5552 EmitJavascriptIntOverflowCheck(compiler, deopt, left, tmp); | 5602 EmitJavascriptIntOverflowCheck(compiler, deopt, left1, left2, tmp); |
5553 } | 5603 } |
5554 } | 5604 } |
5555 | 5605 |
5556 | 5606 |
5557 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(bool opt) const { | 5607 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(bool opt) const { |
5558 const intptr_t kNumInputs = 2; | 5608 const intptr_t kNumInputs = 2; |
5559 const intptr_t kNumTemps = op_kind() == Token::kSHL ? 2 : 1; | 5609 const intptr_t kNumTemps = op_kind() == Token::kSHL ? 2 : 1; |
5560 LocationSummary* summary = | 5610 LocationSummary* summary = |
5561 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5611 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5562 summary->set_in(0, Location::RequiresFpuRegister()); | 5612 summary->set_in(0, Location::Pair(Location::RequiresRegister(), |
5613 Location::RequiresRegister())); | |
5563 summary->set_in(1, Location::RegisterLocation(ECX)); | 5614 summary->set_in(1, Location::RegisterLocation(ECX)); |
5564 summary->set_temp(0, Location::RequiresRegister()); | 5615 summary->set_temp(0, Location::RequiresRegister()); |
5565 if (op_kind() == Token::kSHL) { | 5616 if (op_kind() == Token::kSHL) { |
5566 summary->set_temp(1, Location::RequiresRegister()); | 5617 summary->set_temp(1, Location::RequiresRegister()); |
5567 } | 5618 } |
5568 summary->set_out(0, Location::SameAsFirstInput()); | 5619 summary->set_out(0, Location::SameAsFirstInput()); |
5569 return summary; | 5620 return summary; |
5570 } | 5621 } |
5571 | 5622 |
5572 | 5623 |
5573 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5624 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5574 XmmRegister left = locs()->in(0).fpu_reg(); | 5625 PairLocation* left_pair = locs()->in(0).AsPairLocation(); |
5575 ASSERT(locs()->in(1).reg() == ECX); | 5626 Register left1 = left_pair->At(0).reg(); |
5576 ASSERT(locs()->out(0).fpu_reg() == left); | 5627 Register left2 = left_pair->At(1).reg(); |
5628 PairLocation* out_pair = locs()->out(0).AsPairLocation(); | |
5629 Register out1 = out_pair->At(0).reg(); | |
5630 Register out2 = out_pair->At(1).reg(); | |
5631 ASSERT(out1 == left1); | |
5632 ASSERT(out2 == left2); | |
5577 | 5633 |
5578 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptShiftMintOp); | 5634 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptShiftMintOp); |
5579 Label done; | 5635 Label done; |
5580 __ testl(ECX, ECX); | 5636 __ testl(ECX, ECX); |
5581 __ j(ZERO, &done); // Shift by 0 is a nop. | 5637 __ j(ZERO, &done); // Shift by 0 is a nop. |
5582 __ subl(ESP, Immediate(2 * kWordSize)); | |
5583 __ movq(Address(ESP, 0), left); | |
5584 // Deoptimize if shift count is > 31. | 5638 // Deoptimize if shift count is > 31. |
5585 // sarl operation masks the count to 5 bits and | 5639 // sarl operation masks the count to 5 bits and |
5586 // shrd is undefined with count > operand size (32) | 5640 // shrd is undefined with count > operand size (32) |
5587 // TODO(fschneider): Support shift counts > 31 without deoptimization. | 5641 // TODO(fschneider): Support shift counts > 31 without deoptimization. |
5588 __ SmiUntag(ECX); | 5642 __ SmiUntag(ECX); |
5589 const Immediate& kCountLimit = Immediate(31); | 5643 const Immediate& kCountLimit = Immediate(31); |
5590 __ cmpl(ECX, kCountLimit); | 5644 __ cmpl(ECX, kCountLimit); |
5591 __ j(ABOVE, deopt); | 5645 __ j(ABOVE, deopt); |
5592 switch (op_kind()) { | 5646 switch (op_kind()) { |
5593 case Token::kSHR: { | 5647 case Token::kSHR: { |
5594 Register temp = locs()->temp(0).reg(); | 5648 __ shrd(left1, left2); // Shift count in CL. |
5595 __ movl(temp, Address(ESP, 1 * kWordSize)); // High half. | 5649 __ sarl(left2, ECX); // Shift count in CL. |
5596 __ shrd(Address(ESP, 0), temp); // Shift count in CL. | |
5597 __ sarl(Address(ESP, 1 * kWordSize), ECX); // Shift count in CL. | |
5598 break; | 5650 break; |
5599 } | 5651 } |
5600 case Token::kSHL: { | 5652 case Token::kSHL: { |
5601 Register temp1 = locs()->temp(0).reg(); | 5653 Register temp1 = locs()->temp(0).reg(); |
5602 Register temp2 = locs()->temp(1).reg(); | 5654 Register temp2 = locs()->temp(1).reg(); |
5603 __ movl(temp1, Address(ESP, 0 * kWordSize)); // Low 32 bits. | 5655 __ movl(temp1, left1); // Low 32 bits. |
5604 __ movl(temp2, Address(ESP, 1 * kWordSize)); // High 32 bits. | 5656 __ movl(temp2, left2); // High 32 bits. |
5605 __ shll(Address(ESP, 0 * kWordSize), ECX); // Shift count in CL. | 5657 __ shll(left1, ECX); // Shift count in CL. |
5606 __ shld(Address(ESP, 1 * kWordSize), temp1); // Shift count in CL. | 5658 __ shld(left2, temp1); // Shift count in CL. |
5607 // Check for overflow by shifting back the high 32 bits | 5659 // Check for overflow by shifting back the high 32 bits |
5608 // and comparing with the input. | 5660 // and comparing with the input. |
5609 __ movl(temp1, temp2); | 5661 __ movl(temp1, temp2); |
5610 __ movl(temp2, Address(ESP, 1 * kWordSize)); | 5662 __ movl(temp2, left2); |
5611 __ sarl(temp2, ECX); | 5663 __ sarl(temp2, ECX); |
5612 __ cmpl(temp1, temp2); | 5664 __ cmpl(temp1, temp2); |
5613 __ j(NOT_EQUAL, deopt); | 5665 __ j(NOT_EQUAL, deopt); |
5614 break; | 5666 break; |
5615 } | 5667 } |
5616 default: | 5668 default: |
5617 UNREACHABLE(); | 5669 UNREACHABLE(); |
5618 break; | 5670 break; |
5619 } | 5671 } |
5620 __ movq(left, Address(ESP, 0)); | |
5621 __ addl(ESP, Immediate(2 * kWordSize)); | |
5622 __ Bind(&done); | 5672 __ Bind(&done); |
5623 if (FLAG_throw_on_javascript_int_overflow) { | 5673 if (FLAG_throw_on_javascript_int_overflow) { |
5624 Register tmp = locs()->temp(0).reg(); | 5674 Register tmp = locs()->temp(0).reg(); |
5625 EmitJavascriptIntOverflowCheck(compiler, deopt, left, tmp); | 5675 EmitJavascriptIntOverflowCheck(compiler, deopt, left1, left2, tmp); |
5626 } | 5676 } |
5627 } | 5677 } |
5628 | 5678 |
5629 | 5679 |
5630 LocationSummary* UnaryMintOpInstr::MakeLocationSummary(bool opt) const { | 5680 LocationSummary* UnaryMintOpInstr::MakeLocationSummary(bool opt) const { |
5631 const intptr_t kNumInputs = 1; | 5681 const intptr_t kNumInputs = 1; |
5632 const intptr_t kNumTemps = | 5682 const intptr_t kNumTemps = |
5633 FLAG_throw_on_javascript_int_overflow ? 1 : 0; | 5683 FLAG_throw_on_javascript_int_overflow ? 1 : 0; |
5634 LocationSummary* summary = | 5684 LocationSummary* summary = |
5635 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5685 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5636 summary->set_in(0, Location::RequiresFpuRegister()); | 5686 summary->set_in(0, Location::Pair(Location::RequiresRegister(), |
5687 Location::RequiresRegister())); | |
5637 summary->set_out(0, Location::SameAsFirstInput()); | 5688 summary->set_out(0, Location::SameAsFirstInput()); |
5638 if (FLAG_throw_on_javascript_int_overflow) { | 5689 if (FLAG_throw_on_javascript_int_overflow) { |
5639 summary->set_temp(0, Location::RequiresRegister()); | 5690 summary->set_temp(0, Location::RequiresRegister()); |
Florian Schneider
2014/04/30 18:55:46
temp not needed here anymore.
Cutch
2014/05/14 17:16:19
Done.
| |
5640 } | 5691 } |
5641 return summary; | 5692 return summary; |
5642 } | 5693 } |
5643 | 5694 |
5644 | 5695 |
5645 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5696 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5646 ASSERT(op_kind() == Token::kBIT_NOT); | 5697 ASSERT(op_kind() == Token::kBIT_NOT); |
5647 XmmRegister value = locs()->in(0).fpu_reg(); | 5698 PairLocation* left_pair = locs()->in(0).AsPairLocation(); |
5648 ASSERT(value == locs()->out(0).fpu_reg()); | 5699 Register left1 = left_pair->At(0).reg(); |
5700 Register left2 = left_pair->At(1).reg(); | |
5701 PairLocation* out_pair = locs()->out(0).AsPairLocation(); | |
5702 Register out1 = out_pair->At(0).reg(); | |
5703 Register out2 = out_pair->At(1).reg(); | |
5704 ASSERT(out1 == left1); | |
5705 ASSERT(out2 == left2); | |
5706 | |
5649 Label* deopt = NULL; | 5707 Label* deopt = NULL; |
5650 if (FLAG_throw_on_javascript_int_overflow) { | 5708 if (FLAG_throw_on_javascript_int_overflow) { |
5651 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryMintOp); | 5709 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryMintOp); |
5652 } | 5710 } |
5653 __ pcmpeqq(XMM0, XMM0); // Generate all 1's. | 5711 |
5654 __ pxor(value, XMM0); | 5712 __ notl(left1); |
5713 __ notl(left2); | |
5714 | |
5655 if (FLAG_throw_on_javascript_int_overflow) { | 5715 if (FLAG_throw_on_javascript_int_overflow) { |
5656 Register tmp = locs()->temp(0).reg(); | 5716 Register tmp = locs()->temp(0).reg(); |
5657 EmitJavascriptIntOverflowCheck(compiler, deopt, value, tmp); | 5717 EmitJavascriptIntOverflowCheck(compiler, deopt, left1, left2, tmp); |
5658 } | 5718 } |
5659 } | 5719 } |
5660 | 5720 |
5661 | 5721 |
5662 LocationSummary* ThrowInstr::MakeLocationSummary(bool opt) const { | 5722 LocationSummary* ThrowInstr::MakeLocationSummary(bool opt) const { |
5663 return new LocationSummary(0, 0, LocationSummary::kCall); | 5723 return new LocationSummary(0, 0, LocationSummary::kCall); |
5664 } | 5724 } |
5665 | 5725 |
5666 | 5726 |
5667 | 5727 |
(...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5984 PcDescriptors::kOther, | 6044 PcDescriptors::kOther, |
5985 locs()); | 6045 locs()); |
5986 __ Drop(ArgumentCount()); // Discard arguments. | 6046 __ Drop(ArgumentCount()); // Discard arguments. |
5987 } | 6047 } |
5988 | 6048 |
5989 } // namespace dart | 6049 } // namespace dart |
5990 | 6050 |
5991 #undef __ | 6051 #undef __ |
5992 | 6052 |
5993 #endif // defined TARGET_ARCH_IA32 | 6053 #endif // defined TARGET_ARCH_IA32 |
OLD | NEW |