| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64. |
| 6 #if defined(TARGET_ARCH_X64) | 6 #if defined(TARGET_ARCH_X64) |
| 7 | 7 |
| 8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
| 9 | 9 |
| 10 #include "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 124 | 124 |
| 125 | 125 |
| 126 // Detect pattern when one value is zero and another is a power of 2. | 126 // Detect pattern when one value is zero and another is a power of 2. |
| 127 static bool IsPowerOfTwoKind(intptr_t v1, intptr_t v2) { | 127 static bool IsPowerOfTwoKind(intptr_t v1, intptr_t v2) { |
| 128 return (Utils::IsPowerOfTwo(v1) && (v2 == 0)) || | 128 return (Utils::IsPowerOfTwo(v1) && (v2 == 0)) || |
| 129 (Utils::IsPowerOfTwo(v2) && (v1 == 0)); | 129 (Utils::IsPowerOfTwo(v2) && (v1 == 0)); |
| 130 } | 130 } |
| 131 | 131 |
| 132 | 132 |
| 133 LocationSummary* IfThenElseInstr::MakeLocationSummary() const { | 133 LocationSummary* IfThenElseInstr::MakeLocationSummary() const { |
| 134 const intptr_t kNumInputs = 2; | 134 LocationSummary* locs = comparison()->MakeLocationSummary(); |
| 135 const intptr_t kNumTemps = 0; | |
| 136 LocationSummary* locs = | |
| 137 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | |
| 138 locs->set_in(0, Location::RegisterOrConstant(left())); | |
| 139 // Only one of the inputs can be a constant. Choose register if the first one | |
| 140 // is a constant. | |
| 141 locs->set_in(1, locs->in(0).IsConstant() | |
| 142 ? Location::RequiresRegister() | |
| 143 : Location::RegisterOrConstant(right())); | |
| 144 // TODO(vegorov): support byte register constraints in the register allocator. | 135 // TODO(vegorov): support byte register constraints in the register allocator. |
| 145 locs->set_out(Location::RegisterLocation(RDX)); | 136 locs->set_out(Location::RegisterLocation(RDX)); |
| 146 return locs; | 137 return locs; |
| 147 } | 138 } |
| 148 | 139 |
| 149 | 140 |
| 150 void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 141 void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 151 ASSERT(locs()->out().reg() == RDX); | 142 ASSERT(locs()->out().reg() == RDX); |
| 152 ASSERT(Token::IsEqualityOperator(kind())); | |
| 153 | |
| 154 Location left = locs()->in(0); | |
| 155 Location right = locs()->in(1); | |
| 156 ASSERT(!left.IsConstant() || !right.IsConstant()); | |
| 157 | 143 |
| 158 // Clear upper part of the out register. We are going to use setcc on it | 144 // Clear upper part of the out register. We are going to use setcc on it |
| 159 // which is a byte move. | 145 // which is a byte move. |
| 160 __ xorq(RDX, RDX); | 146 __ xorq(RDX, RDX); |
| 161 | 147 |
| 162 // Compare left and right. For now only equality comparison is supported. | 148 // Emit comparison code. This must not overwrite the result register. |
| 163 // TODO(vegorov): reuse code from the other comparison instructions instead of | 149 BranchLabels labels = { NULL, NULL, NULL }; |
| 164 // generating it inline here. | 150 Condition true_condition = comparison()->EmitComparisonCode(compiler, labels); |
| 165 if (left.IsConstant()) { | |
| 166 __ CompareObject(right.reg(), left.constant(), PP); | |
| 167 } else if (right.IsConstant()) { | |
| 168 __ CompareObject(left.reg(), right.constant(), PP); | |
| 169 } else { | |
| 170 __ cmpq(left.reg(), right.reg()); | |
| 171 } | |
| 172 | |
| 173 Condition true_condition = | |
| 174 ((kind_ == Token::kEQ_STRICT) || (kind_ == Token::kEQ)) ? EQUAL | |
| 175 : NOT_EQUAL; | |
| 176 | 151 |
| 177 const bool is_power_of_two_kind = IsPowerOfTwoKind(if_true_, if_false_); | 152 const bool is_power_of_two_kind = IsPowerOfTwoKind(if_true_, if_false_); |
| 178 | 153 |
| 179 intptr_t true_value = if_true_; | 154 intptr_t true_value = if_true_; |
| 180 intptr_t false_value = if_false_; | 155 intptr_t false_value = if_false_; |
| 181 | 156 |
| 182 if (is_power_of_two_kind) { | 157 if (is_power_of_two_kind) { |
| 183 if (true_value == 0) { | 158 if (true_value == 0) { |
| 184 // We need to have zero in RDX on true_condition. | 159 // We need to have zero in RDX on true_condition. |
| 185 true_condition = NegateCondition(true_condition); | 160 true_condition = NegateCondition(true_condition); |
| (...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 413 __ j(false_condition, labels.false_label); | 388 __ j(false_condition, labels.false_label); |
| 414 | 389 |
| 415 // Fall through or jump to the true successor. | 390 // Fall through or jump to the true successor. |
| 416 if (labels.fall_through != labels.true_label) { | 391 if (labels.fall_through != labels.true_label) { |
| 417 __ jmp(labels.true_label); | 392 __ jmp(labels.true_label); |
| 418 } | 393 } |
| 419 } | 394 } |
| 420 } | 395 } |
| 421 | 396 |
| 422 | 397 |
| 423 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler, | 398 static Condition EmitSmiComparisonOp(FlowGraphCompiler* compiler, |
| 424 const LocationSummary& locs, | 399 const LocationSummary& locs, |
| 425 Token::Kind kind, | 400 Token::Kind kind, |
| 426 BranchLabels labels) { | 401 BranchLabels labels) { |
| 427 Location left = locs.in(0); | 402 Location left = locs.in(0); |
| 428 Location right = locs.in(1); | 403 Location right = locs.in(1); |
| 429 ASSERT(!left.IsConstant() || !right.IsConstant()); | 404 ASSERT(!left.IsConstant() || !right.IsConstant()); |
| 430 | 405 |
| 431 Condition true_condition = TokenKindToSmiCondition(kind); | 406 Condition true_condition = TokenKindToSmiCondition(kind); |
| 432 | 407 |
| 433 if (left.IsConstant()) { | 408 if (left.IsConstant()) { |
| 434 __ CompareObject(right.reg(), left.constant(), PP); | 409 __ CompareObject(right.reg(), left.constant(), PP); |
| 435 true_condition = FlipCondition(true_condition); | 410 true_condition = FlipCondition(true_condition); |
| 436 } else if (right.IsConstant()) { | 411 } else if (right.IsConstant()) { |
| 437 __ CompareObject(left.reg(), right.constant(), PP); | 412 __ CompareObject(left.reg(), right.constant(), PP); |
| 438 } else if (right.IsStackSlot()) { | 413 } else if (right.IsStackSlot()) { |
| 439 __ cmpq(left.reg(), right.ToStackSlotAddress()); | 414 __ cmpq(left.reg(), right.ToStackSlotAddress()); |
| 440 } else { | 415 } else { |
| 441 __ cmpq(left.reg(), right.reg()); | 416 __ cmpq(left.reg(), right.reg()); |
| 442 } | 417 } |
| 443 EmitBranchOnCondition(compiler, true_condition, labels); | 418 return true_condition; |
| 444 } | 419 } |
| 445 | 420 |
| 446 | 421 |
| 447 static Condition TokenKindToDoubleCondition(Token::Kind kind) { | 422 static Condition TokenKindToDoubleCondition(Token::Kind kind) { |
| 448 switch (kind) { | 423 switch (kind) { |
| 449 case Token::kEQ: return EQUAL; | 424 case Token::kEQ: return EQUAL; |
| 450 case Token::kNE: return NOT_EQUAL; | 425 case Token::kNE: return NOT_EQUAL; |
| 451 case Token::kLT: return BELOW; | 426 case Token::kLT: return BELOW; |
| 452 case Token::kGT: return ABOVE; | 427 case Token::kGT: return ABOVE; |
| 453 case Token::kLTE: return BELOW_EQUAL; | 428 case Token::kLTE: return BELOW_EQUAL; |
| 454 case Token::kGTE: return ABOVE_EQUAL; | 429 case Token::kGTE: return ABOVE_EQUAL; |
| 455 default: | 430 default: |
| 456 UNREACHABLE(); | 431 UNREACHABLE(); |
| 457 return OVERFLOW; | 432 return OVERFLOW; |
| 458 } | 433 } |
| 459 } | 434 } |
| 460 | 435 |
| 461 | 436 |
| 462 static void EmitDoubleComparisonOp(FlowGraphCompiler* compiler, | 437 static Condition EmitDoubleComparisonOp(FlowGraphCompiler* compiler, |
| 463 const LocationSummary& locs, | 438 const LocationSummary& locs, |
| 464 Token::Kind kind, | 439 Token::Kind kind, |
| 465 BranchLabels labels) { | 440 BranchLabels labels) { |
| 466 XmmRegister left = locs.in(0).fpu_reg(); | 441 XmmRegister left = locs.in(0).fpu_reg(); |
| 467 XmmRegister right = locs.in(1).fpu_reg(); | 442 XmmRegister right = locs.in(1).fpu_reg(); |
| 468 | 443 |
| 469 __ comisd(left, right); | 444 __ comisd(left, right); |
| 470 | 445 |
| 471 Condition true_condition = TokenKindToDoubleCondition(kind); | 446 Condition true_condition = TokenKindToDoubleCondition(kind); |
| 472 Label* nan_result = (true_condition == NOT_EQUAL) | 447 Label* nan_result = (true_condition == NOT_EQUAL) |
| 473 ? labels.true_label : labels.false_label; | 448 ? labels.true_label : labels.false_label; |
| 474 __ j(PARITY_EVEN, nan_result); | 449 __ j(PARITY_EVEN, nan_result); |
| 475 EmitBranchOnCondition(compiler, true_condition, labels); | 450 return true_condition; |
| 451 } |
| 452 |
| 453 |
| 454 Condition EqualityCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| 455 BranchLabels labels) { |
| 456 if (operation_cid() == kSmiCid) { |
| 457 return EmitSmiComparisonOp(compiler, *locs(), kind(), labels); |
| 458 } else { |
| 459 ASSERT(operation_cid() == kDoubleCid); |
| 460 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); |
| 461 } |
| 476 } | 462 } |
| 477 | 463 |
| 478 | 464 |
| 479 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 465 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 480 ASSERT((kind() == Token::kEQ) || (kind() == Token::kNE)); | 466 ASSERT((kind() == Token::kEQ) || (kind() == Token::kNE)); |
| 481 | 467 |
| 482 Label is_true, is_false; | 468 Label is_true, is_false; |
| 483 BranchLabels labels = { &is_true, &is_false, &is_false }; | 469 BranchLabels labels = { &is_true, &is_false, &is_false }; |
| 470 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 471 EmitBranchOnCondition(compiler, true_condition, labels); |
| 484 | 472 |
| 485 if (operation_cid() == kSmiCid) { | |
| 486 EmitSmiComparisonOp(compiler, *locs(), kind(), labels); | |
| 487 } else { | |
| 488 ASSERT(operation_cid() == kDoubleCid); | |
| 489 EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); | |
| 490 } | |
| 491 Register result = locs()->out().reg(); | 473 Register result = locs()->out().reg(); |
| 492 Label done; | 474 Label done; |
| 493 __ Bind(&is_false); | 475 __ Bind(&is_false); |
| 494 __ LoadObject(result, Bool::False(), PP); | 476 __ LoadObject(result, Bool::False(), PP); |
| 495 __ jmp(&done); | 477 __ jmp(&done); |
| 496 __ Bind(&is_true); | 478 __ Bind(&is_true); |
| 497 __ LoadObject(result, Bool::True(), PP); | 479 __ LoadObject(result, Bool::True(), PP); |
| 498 __ Bind(&done); | 480 __ Bind(&done); |
| 499 } | 481 } |
| 500 | 482 |
| 501 | 483 |
| 502 void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 484 void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 503 BranchInstr* branch) { | 485 BranchInstr* branch) { |
| 504 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); | 486 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); |
| 505 | 487 |
| 506 BranchLabels labels = compiler->CreateBranchLabels(branch); | 488 BranchLabels labels = compiler->CreateBranchLabels(branch); |
| 507 | 489 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 508 if (operation_cid() == kSmiCid) { | 490 EmitBranchOnCondition(compiler, true_condition, labels); |
| 509 EmitSmiComparisonOp(compiler, *locs(), kind(), labels); | |
| 510 } else { | |
| 511 ASSERT(operation_cid() == kDoubleCid); | |
| 512 EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); | |
| 513 } | |
| 514 } | 491 } |
| 515 | 492 |
| 516 | 493 |
| 517 LocationSummary* TestSmiInstr::MakeLocationSummary() const { | 494 LocationSummary* TestSmiInstr::MakeLocationSummary() const { |
| 518 const intptr_t kNumInputs = 2; | 495 const intptr_t kNumInputs = 2; |
| 519 const intptr_t kNumTemps = 0; | 496 const intptr_t kNumTemps = 0; |
| 520 LocationSummary* locs = | 497 LocationSummary* locs = |
| 521 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 498 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 522 locs->set_in(0, Location::RequiresRegister()); | 499 locs->set_in(0, Location::RequiresRegister()); |
| 523 // Only one input can be a constant operand. The case of two constant | 500 // Only one input can be a constant operand. The case of two constant |
| 524 // operands should be handled by constant propagation. | 501 // operands should be handled by constant propagation. |
| 525 locs->set_in(1, Location::RegisterOrConstant(right())); | 502 locs->set_in(1, Location::RegisterOrConstant(right())); |
| 526 return locs; | 503 return locs; |
| 527 } | 504 } |
| 528 | 505 |
| 529 | 506 |
| 530 void TestSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 507 Condition TestSmiInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| 531 // Never emitted outside of the BranchInstr. | 508 BranchLabels labels) { |
| 532 UNREACHABLE(); | |
| 533 } | |
| 534 | |
| 535 | |
| 536 void TestSmiInstr::EmitBranchCode(FlowGraphCompiler* compiler, | |
| 537 BranchInstr* branch) { | |
| 538 BranchLabels labels = compiler->CreateBranchLabels(branch); | |
| 539 | |
| 540 Condition branch_condition = (kind() == Token::kNE) ? NOT_ZERO : ZERO; | |
| 541 Register left_reg = locs()->in(0).reg(); | 509 Register left_reg = locs()->in(0).reg(); |
| 542 Location right = locs()->in(1); | 510 Location right = locs()->in(1); |
| 543 if (right.IsConstant()) { | 511 if (right.IsConstant()) { |
| 544 ASSERT(right.constant().IsSmi()); | 512 ASSERT(right.constant().IsSmi()); |
| 545 const int64_t imm = | 513 const int64_t imm = |
| 546 reinterpret_cast<int64_t>(right.constant().raw()); | 514 reinterpret_cast<int64_t>(right.constant().raw()); |
| 547 __ TestImmediate(left_reg, Immediate(imm), PP); | 515 __ TestImmediate(left_reg, Immediate(imm), PP); |
| 548 } else { | 516 } else { |
| 549 __ testq(left_reg, right.reg()); | 517 __ testq(left_reg, right.reg()); |
| 550 } | 518 } |
| 551 EmitBranchOnCondition(compiler, branch_condition, labels); | 519 Condition true_condition = (kind() == Token::kNE) ? NOT_ZERO : ZERO; |
| 520 return true_condition; |
| 521 } |
| 522 |
| 523 |
| 524 void TestSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 525 // Never emitted outside of the BranchInstr. |
| 526 UNREACHABLE(); |
| 527 } |
| 528 |
| 529 |
| 530 void TestSmiInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 531 BranchInstr* branch) { |
| 532 BranchLabels labels = compiler->CreateBranchLabels(branch); |
| 533 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 534 EmitBranchOnCondition(compiler, true_condition, labels); |
| 552 } | 535 } |
| 553 | 536 |
| 554 | 537 |
| 555 LocationSummary* RelationalOpInstr::MakeLocationSummary() const { | 538 LocationSummary* RelationalOpInstr::MakeLocationSummary() const { |
| 556 const intptr_t kNumInputs = 2; | 539 const intptr_t kNumInputs = 2; |
| 557 const intptr_t kNumTemps = 0; | 540 const intptr_t kNumTemps = 0; |
| 558 if (operation_cid() == kDoubleCid) { | 541 if (operation_cid() == kDoubleCid) { |
| 559 LocationSummary* summary = | 542 LocationSummary* summary = |
| 560 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 543 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 561 summary->set_in(0, Location::RequiresFpuRegister()); | 544 summary->set_in(0, Location::RequiresFpuRegister()); |
| 562 summary->set_in(1, Location::RequiresFpuRegister()); | 545 summary->set_in(1, Location::RequiresFpuRegister()); |
| 563 summary->set_out(Location::RequiresRegister()); | 546 summary->set_out(Location::RequiresRegister()); |
| 564 return summary; | 547 return summary; |
| 565 } | 548 } |
| 566 ASSERT(operation_cid() == kSmiCid); | 549 ASSERT(operation_cid() == kSmiCid); |
| 567 LocationSummary* summary = | 550 LocationSummary* summary = |
| 568 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 551 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 569 summary->set_in(0, Location::RegisterOrConstant(left())); | 552 summary->set_in(0, Location::RegisterOrConstant(left())); |
| 570 // Only one input can be a constant operand. The case of two constant | 553 // Only one input can be a constant operand. The case of two constant |
| 571 // operands should be handled by constant propagation. | 554 // operands should be handled by constant propagation. |
| 572 summary->set_in(1, summary->in(0).IsConstant() | 555 summary->set_in(1, summary->in(0).IsConstant() |
| 573 ? Location::RequiresRegister() | 556 ? Location::RequiresRegister() |
| 574 : Location::RegisterOrConstant(right())); | 557 : Location::RegisterOrConstant(right())); |
| 575 summary->set_out(Location::RequiresRegister()); | 558 summary->set_out(Location::RequiresRegister()); |
| 576 return summary; | 559 return summary; |
| 577 } | 560 } |
| 578 | 561 |
| 579 | 562 |
| 563 Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| 564 BranchLabels labels) { |
| 565 if (operation_cid() == kSmiCid) { |
| 566 return EmitSmiComparisonOp(compiler, *locs(), kind(), labels); |
| 567 } else { |
| 568 ASSERT(operation_cid() == kDoubleCid); |
| 569 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); |
| 570 } |
| 571 } |
| 572 |
| 573 |
| 580 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 574 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 581 Label is_true, is_false; | 575 Label is_true, is_false; |
| 582 BranchLabels labels = { &is_true, &is_false, &is_false }; | 576 BranchLabels labels = { &is_true, &is_false, &is_false }; |
| 577 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 578 EmitBranchOnCondition(compiler, true_condition, labels); |
| 583 | 579 |
| 584 if (operation_cid() == kSmiCid) { | |
| 585 EmitSmiComparisonOp(compiler, *locs(), kind(), labels); | |
| 586 } else { | |
| 587 ASSERT(operation_cid() == kDoubleCid); | |
| 588 EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); | |
| 589 } | |
| 590 Register result = locs()->out().reg(); | 580 Register result = locs()->out().reg(); |
| 591 Label done; | 581 Label done; |
| 592 __ Bind(&is_false); | 582 __ Bind(&is_false); |
| 593 __ LoadObject(result, Bool::False(), PP); | 583 __ LoadObject(result, Bool::False(), PP); |
| 594 __ jmp(&done); | 584 __ jmp(&done); |
| 595 __ Bind(&is_true); | 585 __ Bind(&is_true); |
| 596 __ LoadObject(result, Bool::True(), PP); | 586 __ LoadObject(result, Bool::True(), PP); |
| 597 __ Bind(&done); | 587 __ Bind(&done); |
| 598 } | 588 } |
| 599 | 589 |
| 600 | 590 |
| 601 void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 591 void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 602 BranchInstr* branch) { | 592 BranchInstr* branch) { |
| 603 BranchLabels labels = compiler->CreateBranchLabels(branch); | 593 BranchLabels labels = compiler->CreateBranchLabels(branch); |
| 604 | 594 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 605 if (operation_cid() == kSmiCid) { | 595 EmitBranchOnCondition(compiler, true_condition, labels); |
| 606 EmitSmiComparisonOp(compiler, *locs(), kind(), labels); | |
| 607 } else { | |
| 608 ASSERT(operation_cid() == kDoubleCid); | |
| 609 EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); | |
| 610 } | |
| 611 } | 596 } |
| 612 | 597 |
| 613 | 598 |
| 614 LocationSummary* NativeCallInstr::MakeLocationSummary() const { | 599 LocationSummary* NativeCallInstr::MakeLocationSummary() const { |
| 615 const intptr_t kNumInputs = 0; | 600 const intptr_t kNumInputs = 0; |
| 616 const intptr_t kNumTemps = 3; | 601 const intptr_t kNumTemps = 3; |
| 617 LocationSummary* locs = | 602 LocationSummary* locs = |
| 618 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 603 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 619 locs->set_temp(0, Location::RegisterLocation(RAX)); | 604 locs->set_temp(0, Location::RegisterLocation(RAX)); |
| 620 locs->set_temp(1, Location::RegisterLocation(RBX)); | 605 locs->set_temp(1, Location::RegisterLocation(RBX)); |
| (...skipping 3774 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4395 // Only one of the inputs can be a constant. Choose register if the first one | 4380 // Only one of the inputs can be a constant. Choose register if the first one |
| 4396 // is a constant. | 4381 // is a constant. |
| 4397 locs->set_in(1, locs->in(0).IsConstant() | 4382 locs->set_in(1, locs->in(0).IsConstant() |
| 4398 ? Location::RequiresRegister() | 4383 ? Location::RequiresRegister() |
| 4399 : Location::RegisterOrConstant(right())); | 4384 : Location::RegisterOrConstant(right())); |
| 4400 locs->set_out(Location::RequiresRegister()); | 4385 locs->set_out(Location::RequiresRegister()); |
| 4401 return locs; | 4386 return locs; |
| 4402 } | 4387 } |
| 4403 | 4388 |
| 4404 | 4389 |
| 4405 static void EmitStrictComparison(FlowGraphCompiler* compiler, | 4390 Condition StrictCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| 4406 StrictCompareInstr* compare, | 4391 BranchLabels labels) { |
| 4407 BranchLabels labels) { | 4392 Location left = locs()->in(0); |
| 4408 LocationSummary* locs = compare->locs(); | 4393 Location right = locs()->in(1); |
| 4409 bool needs_number_check = compare->needs_number_check(); | |
| 4410 intptr_t token_pos = compare->token_pos(); | |
| 4411 Token::Kind kind = compare->kind(); | |
| 4412 Location left = locs->in(0); | |
| 4413 Location right = locs->in(1); | |
| 4414 ASSERT(!left.IsConstant() || !right.IsConstant()); | 4394 ASSERT(!left.IsConstant() || !right.IsConstant()); |
| 4415 if (left.IsConstant()) { | 4395 if (left.IsConstant()) { |
| 4416 compiler->EmitEqualityRegConstCompare(right.reg(), | 4396 compiler->EmitEqualityRegConstCompare(right.reg(), |
| 4417 left.constant(), | 4397 left.constant(), |
| 4418 needs_number_check, | 4398 needs_number_check(), |
| 4419 token_pos); | 4399 token_pos()); |
| 4420 } else if (right.IsConstant()) { | 4400 } else if (right.IsConstant()) { |
| 4421 compiler->EmitEqualityRegConstCompare(left.reg(), | 4401 compiler->EmitEqualityRegConstCompare(left.reg(), |
| 4422 right.constant(), | 4402 right.constant(), |
| 4423 needs_number_check, | 4403 needs_number_check(), |
| 4424 token_pos); | 4404 token_pos()); |
| 4425 } else { | 4405 } else { |
| 4426 compiler->EmitEqualityRegRegCompare(left.reg(), | 4406 compiler->EmitEqualityRegRegCompare(left.reg(), |
| 4427 right.reg(), | 4407 right.reg(), |
| 4428 needs_number_check, | 4408 needs_number_check(), |
| 4429 token_pos); | 4409 token_pos()); |
| 4430 } | 4410 } |
| 4431 | 4411 |
| 4432 Condition true_condition = (kind == Token::kEQ_STRICT) ? EQUAL : NOT_EQUAL; | 4412 Condition true_condition = (kind() == Token::kEQ_STRICT) ? EQUAL : NOT_EQUAL; |
| 4433 EmitBranchOnCondition(compiler, true_condition, labels); | 4413 return true_condition; |
| 4434 } | 4414 } |
| 4435 | 4415 |
| 4436 | 4416 |
| 4437 // Special code for numbers (compare values instead of references.) | |
| 4438 void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4417 void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4439 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); | 4418 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); |
| 4440 | 4419 |
| 4441 Label is_true, is_false; | 4420 Label is_true, is_false; |
| 4442 BranchLabels labels = { &is_true, &is_false, &is_false }; | 4421 BranchLabels labels = { &is_true, &is_false, &is_false }; |
| 4443 | 4422 |
| 4444 EmitStrictComparison(compiler, this, labels); | 4423 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 4424 EmitBranchOnCondition(compiler, true_condition, labels); |
| 4445 | 4425 |
| 4446 Register result = locs()->out().reg(); | 4426 Register result = locs()->out().reg(); |
| 4447 Label done; | 4427 Label done; |
| 4448 __ Bind(&is_false); | 4428 __ Bind(&is_false); |
| 4449 __ LoadObject(result, Bool::False(), PP); | 4429 __ LoadObject(result, Bool::False(), PP); |
| 4450 __ jmp(&done); | 4430 __ jmp(&done); |
| 4451 __ Bind(&is_true); | 4431 __ Bind(&is_true); |
| 4452 __ LoadObject(result, Bool::True(), PP); | 4432 __ LoadObject(result, Bool::True(), PP); |
| 4453 __ Bind(&done); | 4433 __ Bind(&done); |
| 4454 } | 4434 } |
| 4455 | 4435 |
| 4456 | 4436 |
| 4457 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 4437 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 4458 BranchInstr* branch) { | 4438 BranchInstr* branch) { |
| 4459 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); | 4439 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); |
| 4460 | 4440 |
| 4461 BranchLabels labels = compiler->CreateBranchLabels(branch); | 4441 BranchLabels labels = compiler->CreateBranchLabels(branch); |
| 4462 | 4442 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 4463 EmitStrictComparison(compiler, this, labels); | 4443 EmitBranchOnCondition(compiler, true_condition, labels); |
| 4464 } | 4444 } |
| 4465 | 4445 |
| 4466 | 4446 |
| 4467 LocationSummary* ClosureCallInstr::MakeLocationSummary() const { | 4447 LocationSummary* ClosureCallInstr::MakeLocationSummary() const { |
| 4468 const intptr_t kNumInputs = 0; | 4448 const intptr_t kNumInputs = 0; |
| 4469 const intptr_t kNumTemps = 1; | 4449 const intptr_t kNumTemps = 1; |
| 4470 LocationSummary* result = | 4450 LocationSummary* result = |
| 4471 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 4451 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 4472 result->set_out(Location::RegisterLocation(RAX)); | 4452 result->set_out(Location::RegisterLocation(RAX)); |
| 4473 result->set_temp(0, Location::RegisterLocation(R10)); // Arg. descriptor. | 4453 result->set_temp(0, Location::RegisterLocation(R10)); // Arg. descriptor. |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4572 PcDescriptors::kOther, | 4552 PcDescriptors::kOther, |
| 4573 locs()); | 4553 locs()); |
| 4574 __ Drop(2); // Discard type arguments and receiver. | 4554 __ Drop(2); // Discard type arguments and receiver. |
| 4575 } | 4555 } |
| 4576 | 4556 |
| 4577 } // namespace dart | 4557 } // namespace dart |
| 4578 | 4558 |
| 4579 #undef __ | 4559 #undef __ |
| 4580 | 4560 |
| 4581 #endif // defined TARGET_ARCH_X64 | 4561 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |