Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_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 |