| 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 392 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 403 case ABOVE: return BELOW; | 403 case ABOVE: return BELOW; |
| 404 case ABOVE_EQUAL: return BELOW_EQUAL; | 404 case ABOVE_EQUAL: return BELOW_EQUAL; |
| 405 default: | 405 default: |
| 406 UNIMPLEMENTED(); | 406 UNIMPLEMENTED(); |
| 407 return EQUAL; | 407 return EQUAL; |
| 408 } | 408 } |
| 409 } | 409 } |
| 410 | 410 |
| 411 | 411 |
| 412 static void EmitBranchOnCondition(FlowGraphCompiler* compiler, | 412 static void EmitBranchOnCondition(FlowGraphCompiler* compiler, |
| 413 TargetEntryInstr* true_successor, | 413 Condition true_condition, |
| 414 TargetEntryInstr* false_successor, | 414 BranchLabels labels) { |
| 415 Condition true_condition) { | 415 if (labels.fall_through == labels.false_label) { |
| 416 if (compiler->CanFallThroughTo(false_successor)) { | |
| 417 // If the next block is the false successor, fall through to it. | 416 // If the next block is the false successor, fall through to it. |
| 418 __ j(true_condition, compiler->GetJumpLabel(true_successor)); | 417 __ j(true_condition, labels.true_label); |
| 419 } else { | 418 } else { |
| 420 // If the next block is not the false successor, branch to it. | 419 // If the next block is not the false successor, branch to it. |
| 421 Condition false_condition = NegateCondition(true_condition); | 420 Condition false_condition = NegateCondition(true_condition); |
| 422 __ j(false_condition, compiler->GetJumpLabel(false_successor)); | 421 __ j(false_condition, labels.false_label); |
| 423 | 422 |
| 424 // Fall through or jump to the true successor. | 423 // Fall through or jump to the true successor. |
| 425 if (!compiler->CanFallThroughTo(true_successor)) { | 424 if (labels.fall_through != labels.true_label) { |
| 426 __ jmp(compiler->GetJumpLabel(true_successor)); | 425 __ jmp(labels.true_label); |
| 427 } | 426 } |
| 428 } | 427 } |
| 429 } | 428 } |
| 430 | 429 |
| 431 | 430 |
| 432 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler, | 431 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler, |
| 433 const LocationSummary& locs, | 432 const LocationSummary& locs, |
| 434 Token::Kind kind, | 433 Token::Kind kind, |
| 435 BranchInstr* branch) { | 434 BranchLabels labels) { |
| 436 Location left = locs.in(0); | 435 Location left = locs.in(0); |
| 437 Location right = locs.in(1); | 436 Location right = locs.in(1); |
| 438 ASSERT(!left.IsConstant() || !right.IsConstant()); | 437 ASSERT(!left.IsConstant() || !right.IsConstant()); |
| 439 | 438 |
| 440 Condition true_condition = TokenKindToSmiCondition(kind); | 439 Condition true_condition = TokenKindToSmiCondition(kind); |
| 441 | 440 |
| 442 if (left.IsConstant()) { | 441 if (left.IsConstant()) { |
| 443 __ CompareObject(right.reg(), left.constant(), PP); | 442 __ CompareObject(right.reg(), left.constant(), PP); |
| 444 true_condition = FlipCondition(true_condition); | 443 true_condition = FlipCondition(true_condition); |
| 445 } else if (right.IsConstant()) { | 444 } else if (right.IsConstant()) { |
| 446 __ CompareObject(left.reg(), right.constant(), PP); | 445 __ CompareObject(left.reg(), right.constant(), PP); |
| 447 } else if (right.IsStackSlot()) { | 446 } else if (right.IsStackSlot()) { |
| 448 __ cmpq(left.reg(), right.ToStackSlotAddress()); | 447 __ cmpq(left.reg(), right.ToStackSlotAddress()); |
| 449 } else { | 448 } else { |
| 450 __ cmpq(left.reg(), right.reg()); | 449 __ cmpq(left.reg(), right.reg()); |
| 451 } | 450 } |
| 452 | 451 EmitBranchOnCondition(compiler, true_condition, labels); |
| 453 if (branch != NULL) { | |
| 454 EmitBranchOnCondition(compiler, | |
| 455 branch->true_successor(), | |
| 456 branch->false_successor(), | |
| 457 true_condition); | |
| 458 } else { | |
| 459 Register result = locs.out().reg(); | |
| 460 Label done, is_true; | |
| 461 __ j(true_condition, &is_true); | |
| 462 __ LoadObject(result, Bool::False(), PP); | |
| 463 __ jmp(&done); | |
| 464 __ Bind(&is_true); | |
| 465 __ LoadObject(result, Bool::True(), PP); | |
| 466 __ Bind(&done); | |
| 467 } | |
| 468 } | 452 } |
| 469 | 453 |
| 470 | 454 |
| 471 static Condition TokenKindToDoubleCondition(Token::Kind kind) { | 455 static Condition TokenKindToDoubleCondition(Token::Kind kind) { |
| 472 switch (kind) { | 456 switch (kind) { |
| 473 case Token::kEQ: return EQUAL; | 457 case Token::kEQ: return EQUAL; |
| 474 case Token::kNE: return NOT_EQUAL; | 458 case Token::kNE: return NOT_EQUAL; |
| 475 case Token::kLT: return BELOW; | 459 case Token::kLT: return BELOW; |
| 476 case Token::kGT: return ABOVE; | 460 case Token::kGT: return ABOVE; |
| 477 case Token::kLTE: return BELOW_EQUAL; | 461 case Token::kLTE: return BELOW_EQUAL; |
| 478 case Token::kGTE: return ABOVE_EQUAL; | 462 case Token::kGTE: return ABOVE_EQUAL; |
| 479 default: | 463 default: |
| 480 UNREACHABLE(); | 464 UNREACHABLE(); |
| 481 return OVERFLOW; | 465 return OVERFLOW; |
| 482 } | 466 } |
| 483 } | 467 } |
| 484 | 468 |
| 485 | 469 |
| 486 static void EmitDoubleCompareBranch(FlowGraphCompiler* compiler, | 470 static void EmitDoubleComparisonOp(FlowGraphCompiler* compiler, |
| 487 Condition true_condition, | 471 const LocationSummary& locs, |
| 488 FpuRegister left, | 472 Token::Kind kind, |
| 489 FpuRegister right, | 473 BranchLabels labels) { |
| 490 BranchInstr* branch) { | 474 XmmRegister left = locs.in(0).fpu_reg(); |
| 491 ASSERT(branch != NULL); | 475 XmmRegister right = locs.in(1).fpu_reg(); |
| 476 |
| 492 __ comisd(left, right); | 477 __ comisd(left, right); |
| 493 BlockEntryInstr* nan_result = (true_condition == NOT_EQUAL) ? | 478 |
| 494 branch->true_successor() : branch->false_successor(); | 479 Condition true_condition = TokenKindToDoubleCondition(kind); |
| 495 __ j(PARITY_EVEN, compiler->GetJumpLabel(nan_result)); | 480 Label* nan_result = (true_condition == NOT_EQUAL) |
| 496 EmitBranchOnCondition(compiler, | 481 ? labels.true_label : labels.false_label; |
| 497 branch->true_successor(), | 482 __ j(PARITY_EVEN, nan_result); |
| 498 branch->false_successor(), | 483 EmitBranchOnCondition(compiler, true_condition, labels); |
| 499 true_condition); | |
| 500 } | 484 } |
| 501 | 485 |
| 502 | 486 |
| 503 static void EmitDoubleCompareBool(FlowGraphCompiler* compiler, | 487 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 504 Condition true_condition, | 488 ASSERT((kind() == Token::kEQ) || (kind() == Token::kNE)); |
| 505 FpuRegister left, | 489 |
| 506 FpuRegister right, | 490 Label is_true, is_false; |
| 507 Register result) { | 491 BranchLabels labels = { &is_true, &is_false, &is_false }; |
| 508 __ comisd(left, right); | 492 |
| 509 Label is_false, is_true, done; | 493 if (operation_cid() == kSmiCid) { |
| 510 // x == NaN -> false, x != NaN -> true. | 494 EmitSmiComparisonOp(compiler, *locs(), kind(), labels); |
| 511 Label* nan_label = (true_condition == NOT_EQUAL) ? &is_true : &is_false; | 495 } else { |
| 512 __ j(PARITY_EVEN, nan_label, Assembler::kNearJump); | 496 ASSERT(operation_cid() == kDoubleCid); |
| 513 __ j(true_condition, &is_true, Assembler::kNearJump); | 497 EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); |
| 498 } |
| 499 Register result = locs()->out().reg(); |
| 500 Label done; |
| 514 __ Bind(&is_false); | 501 __ Bind(&is_false); |
| 515 __ LoadObject(result, Bool::False(), PP); | 502 __ LoadObject(result, Bool::False(), PP); |
| 516 __ jmp(&done); | 503 __ jmp(&done); |
| 517 __ Bind(&is_true); | 504 __ Bind(&is_true); |
| 518 __ LoadObject(result, Bool::True(), PP); | 505 __ LoadObject(result, Bool::True(), PP); |
| 519 __ Bind(&done); | 506 __ Bind(&done); |
| 520 } | 507 } |
| 521 | 508 |
| 522 | 509 |
| 523 static void EmitDoubleComparisonOp(FlowGraphCompiler* compiler, | 510 void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 524 const LocationSummary& locs, | 511 BranchInstr* branch) { |
| 525 Token::Kind kind, | 512 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); |
| 526 BranchInstr* branch) { | |
| 527 XmmRegister left = locs.in(0).fpu_reg(); | |
| 528 XmmRegister right = locs.in(1).fpu_reg(); | |
| 529 | 513 |
| 530 Condition true_condition = TokenKindToDoubleCondition(kind); | 514 BranchLabels labels = compiler->CreateBranchLabels(branch); |
| 531 if (branch != NULL) { | 515 |
| 532 EmitDoubleCompareBranch(compiler, true_condition, left, right, branch); | 516 if (operation_cid() == kSmiCid) { |
| 533 } else { | 517 EmitSmiComparisonOp(compiler, *locs(), kind(), labels); |
| 534 EmitDoubleCompareBool(compiler, true_condition, | 518 } else { |
| 535 left, right, locs.out().reg()); | 519 ASSERT(operation_cid() == kDoubleCid); |
| 520 EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); |
| 536 } | 521 } |
| 537 } | 522 } |
| 538 | 523 |
| 539 | 524 |
| 540 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 541 ASSERT((kind() == Token::kEQ) || (kind() == Token::kNE)); | |
| 542 BranchInstr* kNoBranch = NULL; | |
| 543 if (operation_cid() == kSmiCid) { | |
| 544 EmitSmiComparisonOp(compiler, *locs(), kind(), kNoBranch); | |
| 545 return; | |
| 546 } | |
| 547 if (operation_cid() == kDoubleCid) { | |
| 548 EmitDoubleComparisonOp(compiler, *locs(), kind(), kNoBranch); | |
| 549 return; | |
| 550 } | |
| 551 UNREACHABLE(); | |
| 552 } | |
| 553 | |
| 554 | |
| 555 void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, | |
| 556 BranchInstr* branch) { | |
| 557 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); | |
| 558 if (operation_cid() == kSmiCid) { | |
| 559 EmitSmiComparisonOp(compiler, *locs(), kind(), branch); | |
| 560 return; | |
| 561 } | |
| 562 if (operation_cid() == kDoubleCid) { | |
| 563 EmitDoubleComparisonOp(compiler, *locs(), kind(), branch); | |
| 564 return; | |
| 565 } | |
| 566 UNREACHABLE(); | |
| 567 } | |
| 568 | |
| 569 | |
| 570 LocationSummary* TestSmiInstr::MakeLocationSummary() const { | 525 LocationSummary* TestSmiInstr::MakeLocationSummary() const { |
| 571 const intptr_t kNumInputs = 2; | 526 const intptr_t kNumInputs = 2; |
| 572 const intptr_t kNumTemps = 0; | 527 const intptr_t kNumTemps = 0; |
| 573 LocationSummary* locs = | 528 LocationSummary* locs = |
| 574 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 529 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 575 locs->set_in(0, Location::RequiresRegister()); | 530 locs->set_in(0, Location::RequiresRegister()); |
| 576 // Only one input can be a constant operand. The case of two constant | 531 // Only one input can be a constant operand. The case of two constant |
| 577 // operands should be handled by constant propagation. | 532 // operands should be handled by constant propagation. |
| 578 locs->set_in(1, Location::RegisterOrConstant(right())); | 533 locs->set_in(1, Location::RegisterOrConstant(right())); |
| 579 return locs; | 534 return locs; |
| 580 } | 535 } |
| 581 | 536 |
| 582 | 537 |
| 583 void TestSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 538 void TestSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 584 // Never emitted outside of the BranchInstr. | 539 // Never emitted outside of the BranchInstr. |
| 585 UNREACHABLE(); | 540 UNREACHABLE(); |
| 586 } | 541 } |
| 587 | 542 |
| 588 | 543 |
| 589 void TestSmiInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 544 void TestSmiInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 590 BranchInstr* branch) { | 545 BranchInstr* branch) { |
| 546 BranchLabels labels = compiler->CreateBranchLabels(branch); |
| 547 |
| 591 Condition branch_condition = (kind() == Token::kNE) ? NOT_ZERO : ZERO; | 548 Condition branch_condition = (kind() == Token::kNE) ? NOT_ZERO : ZERO; |
| 592 Register left_reg = locs()->in(0).reg(); | 549 Register left_reg = locs()->in(0).reg(); |
| 593 Location right = locs()->in(1); | 550 Location right = locs()->in(1); |
| 594 if (right.IsConstant()) { | 551 if (right.IsConstant()) { |
| 595 ASSERT(right.constant().IsSmi()); | 552 ASSERT(right.constant().IsSmi()); |
| 596 const int64_t imm = | 553 const int64_t imm = |
| 597 reinterpret_cast<int64_t>(right.constant().raw()); | 554 reinterpret_cast<int64_t>(right.constant().raw()); |
| 598 __ TestImmediate(left_reg, Immediate(imm), PP); | 555 __ TestImmediate(left_reg, Immediate(imm), PP); |
| 599 } else { | 556 } else { |
| 600 __ testq(left_reg, right.reg()); | 557 __ testq(left_reg, right.reg()); |
| 601 } | 558 } |
| 602 EmitBranchOnCondition(compiler, | 559 EmitBranchOnCondition(compiler, branch_condition, labels); |
| 603 branch->true_successor(), | |
| 604 branch->false_successor(), | |
| 605 branch_condition); | |
| 606 } | 560 } |
| 607 | 561 |
| 608 | 562 |
| 609 LocationSummary* RelationalOpInstr::MakeLocationSummary() const { | 563 LocationSummary* RelationalOpInstr::MakeLocationSummary() const { |
| 610 const intptr_t kNumInputs = 2; | 564 const intptr_t kNumInputs = 2; |
| 611 const intptr_t kNumTemps = 0; | 565 const intptr_t kNumTemps = 0; |
| 612 if (operation_cid() == kDoubleCid) { | 566 if (operation_cid() == kDoubleCid) { |
| 613 LocationSummary* summary = | 567 LocationSummary* summary = |
| 614 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 568 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 615 summary->set_in(0, Location::RequiresFpuRegister()); | 569 summary->set_in(0, Location::RequiresFpuRegister()); |
| 616 summary->set_in(1, Location::RequiresFpuRegister()); | 570 summary->set_in(1, Location::RequiresFpuRegister()); |
| 617 summary->set_out(Location::RequiresRegister()); | 571 summary->set_out(Location::RequiresRegister()); |
| 618 return summary; | 572 return summary; |
| 619 } | 573 } |
| 620 ASSERT(operation_cid() == kSmiCid); | 574 ASSERT(operation_cid() == kSmiCid); |
| 621 LocationSummary* summary = | 575 LocationSummary* summary = |
| 622 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 576 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 623 summary->set_in(0, Location::RegisterOrConstant(left())); | 577 summary->set_in(0, Location::RegisterOrConstant(left())); |
| 624 // Only one input can be a constant operand. The case of two constant | 578 // Only one input can be a constant operand. The case of two constant |
| 625 // operands should be handled by constant propagation. | 579 // operands should be handled by constant propagation. |
| 626 summary->set_in(1, summary->in(0).IsConstant() | 580 summary->set_in(1, summary->in(0).IsConstant() |
| 627 ? Location::RequiresRegister() | 581 ? Location::RequiresRegister() |
| 628 : Location::RegisterOrConstant(right())); | 582 : Location::RegisterOrConstant(right())); |
| 629 summary->set_out(Location::RequiresRegister()); | 583 summary->set_out(Location::RequiresRegister()); |
| 630 return summary; | 584 return summary; |
| 631 } | 585 } |
| 632 | 586 |
| 633 | 587 |
| 634 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 588 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 589 Label is_true, is_false; |
| 590 BranchLabels labels = { &is_true, &is_false, &is_false }; |
| 591 |
| 635 if (operation_cid() == kSmiCid) { | 592 if (operation_cid() == kSmiCid) { |
| 636 EmitSmiComparisonOp(compiler, *locs(), kind(), NULL); | 593 EmitSmiComparisonOp(compiler, *locs(), kind(), labels); |
| 637 return; | 594 } else { |
| 595 ASSERT(operation_cid() == kDoubleCid); |
| 596 EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); |
| 638 } | 597 } |
| 639 ASSERT(operation_cid() == kDoubleCid); | 598 Register result = locs()->out().reg(); |
| 640 EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL); | 599 Label done; |
| 600 __ Bind(&is_false); |
| 601 __ LoadObject(result, Bool::False(), PP); |
| 602 __ jmp(&done); |
| 603 __ Bind(&is_true); |
| 604 __ LoadObject(result, Bool::True(), PP); |
| 605 __ Bind(&done); |
| 641 } | 606 } |
| 642 | 607 |
| 643 | 608 |
| 644 void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 609 void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 645 BranchInstr* branch) { | 610 BranchInstr* branch) { |
| 611 BranchLabels labels = compiler->CreateBranchLabels(branch); |
| 612 |
| 646 if (operation_cid() == kSmiCid) { | 613 if (operation_cid() == kSmiCid) { |
| 647 EmitSmiComparisonOp(compiler, *locs(), kind(), branch); | 614 EmitSmiComparisonOp(compiler, *locs(), kind(), labels); |
| 648 return; | 615 } else { |
| 616 ASSERT(operation_cid() == kDoubleCid); |
| 617 EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); |
| 649 } | 618 } |
| 650 ASSERT(operation_cid() == kDoubleCid); | |
| 651 EmitDoubleComparisonOp(compiler, *locs(), kind(), branch); | |
| 652 } | 619 } |
| 653 | 620 |
| 654 | 621 |
| 655 LocationSummary* NativeCallInstr::MakeLocationSummary() const { | 622 LocationSummary* NativeCallInstr::MakeLocationSummary() const { |
| 656 const intptr_t kNumInputs = 0; | 623 const intptr_t kNumInputs = 0; |
| 657 const intptr_t kNumTemps = 3; | 624 const intptr_t kNumTemps = 3; |
| 658 LocationSummary* locs = | 625 LocationSummary* locs = |
| 659 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 626 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 660 locs->set_temp(0, Location::RegisterLocation(RAX)); | 627 locs->set_temp(0, Location::RegisterLocation(RAX)); |
| 661 locs->set_temp(1, Location::RegisterLocation(RBX)); | 628 locs->set_temp(1, Location::RegisterLocation(RBX)); |
| (...skipping 3774 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4436 // Only one of the inputs can be a constant. Choose register if the first one | 4403 // Only one of the inputs can be a constant. Choose register if the first one |
| 4437 // is a constant. | 4404 // is a constant. |
| 4438 locs->set_in(1, locs->in(0).IsConstant() | 4405 locs->set_in(1, locs->in(0).IsConstant() |
| 4439 ? Location::RequiresRegister() | 4406 ? Location::RequiresRegister() |
| 4440 : Location::RegisterOrConstant(right())); | 4407 : Location::RegisterOrConstant(right())); |
| 4441 locs->set_out(Location::RequiresRegister()); | 4408 locs->set_out(Location::RequiresRegister()); |
| 4442 return locs; | 4409 return locs; |
| 4443 } | 4410 } |
| 4444 | 4411 |
| 4445 | 4412 |
| 4413 static void EmitStrictComparison(FlowGraphCompiler* compiler, |
| 4414 StrictCompareInstr* compare, |
| 4415 BranchLabels labels) { |
| 4416 LocationSummary* locs = compare->locs(); |
| 4417 bool needs_number_check = compare->needs_number_check(); |
| 4418 intptr_t token_pos = compare->token_pos(); |
| 4419 Token::Kind kind = compare->kind(); |
| 4420 Location left = locs->in(0); |
| 4421 Location right = locs->in(1); |
| 4422 ASSERT(!left.IsConstant() || !right.IsConstant()); |
| 4423 if (left.IsConstant()) { |
| 4424 compiler->EmitEqualityRegConstCompare(right.reg(), |
| 4425 left.constant(), |
| 4426 needs_number_check, |
| 4427 token_pos); |
| 4428 } else if (right.IsConstant()) { |
| 4429 compiler->EmitEqualityRegConstCompare(left.reg(), |
| 4430 right.constant(), |
| 4431 needs_number_check, |
| 4432 token_pos); |
| 4433 } else { |
| 4434 compiler->EmitEqualityRegRegCompare(left.reg(), |
| 4435 right.reg(), |
| 4436 needs_number_check, |
| 4437 token_pos); |
| 4438 } |
| 4439 |
| 4440 Condition true_condition = (kind == Token::kEQ_STRICT) ? EQUAL : NOT_EQUAL; |
| 4441 EmitBranchOnCondition(compiler, true_condition, labels); |
| 4442 } |
| 4443 |
| 4444 |
| 4446 // Special code for numbers (compare values instead of references.) | 4445 // Special code for numbers (compare values instead of references.) |
| 4447 void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4446 void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4448 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); | 4447 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); |
| 4449 Location left = locs()->in(0); | 4448 |
| 4450 Location right = locs()->in(1); | 4449 Label is_true, is_false; |
| 4451 ASSERT(!left.IsConstant() || !right.IsConstant()); | 4450 BranchLabels labels = { &is_true, &is_false, &is_false }; |
| 4452 if (left.IsConstant()) { | 4451 |
| 4453 compiler->EmitEqualityRegConstCompare(right.reg(), | 4452 EmitStrictComparison(compiler, this, labels); |
| 4454 left.constant(), | |
| 4455 needs_number_check(), | |
| 4456 token_pos()); | |
| 4457 } else if (right.IsConstant()) { | |
| 4458 compiler->EmitEqualityRegConstCompare(left.reg(), | |
| 4459 right.constant(), | |
| 4460 needs_number_check(), | |
| 4461 token_pos()); | |
| 4462 } else { | |
| 4463 compiler->EmitEqualityRegRegCompare(left.reg(), | |
| 4464 right.reg(), | |
| 4465 needs_number_check(), | |
| 4466 token_pos()); | |
| 4467 } | |
| 4468 | 4453 |
| 4469 Register result = locs()->out().reg(); | 4454 Register result = locs()->out().reg(); |
| 4470 Label load_true, done; | 4455 Label done; |
| 4471 Condition true_condition = (kind() == Token::kEQ_STRICT) ? EQUAL : NOT_EQUAL; | 4456 __ Bind(&is_false); |
| 4472 __ j(true_condition, &load_true, Assembler::kNearJump); | |
| 4473 __ LoadObject(result, Bool::False(), PP); | 4457 __ LoadObject(result, Bool::False(), PP); |
| 4474 __ jmp(&done, Assembler::kNearJump); | 4458 __ jmp(&done); |
| 4475 __ Bind(&load_true); | 4459 __ Bind(&is_true); |
| 4476 __ LoadObject(result, Bool::True(), PP); | 4460 __ LoadObject(result, Bool::True(), PP); |
| 4477 __ Bind(&done); | 4461 __ Bind(&done); |
| 4478 } | 4462 } |
| 4479 | 4463 |
| 4480 | 4464 |
| 4481 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 4465 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 4482 BranchInstr* branch) { | 4466 BranchInstr* branch) { |
| 4483 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); | 4467 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); |
| 4484 Location left = locs()->in(0); | |
| 4485 Location right = locs()->in(1); | |
| 4486 ASSERT(!left.IsConstant() || !right.IsConstant()); | |
| 4487 if (left.IsConstant()) { | |
| 4488 compiler->EmitEqualityRegConstCompare(right.reg(), | |
| 4489 left.constant(), | |
| 4490 needs_number_check(), | |
| 4491 token_pos()); | |
| 4492 } else if (right.IsConstant()) { | |
| 4493 compiler->EmitEqualityRegConstCompare(left.reg(), | |
| 4494 right.constant(), | |
| 4495 needs_number_check(), | |
| 4496 token_pos()); | |
| 4497 } else { | |
| 4498 compiler->EmitEqualityRegRegCompare(left.reg(), | |
| 4499 right.reg(), | |
| 4500 needs_number_check(), | |
| 4501 token_pos()); | |
| 4502 } | |
| 4503 | 4468 |
| 4504 Condition true_condition = (kind() == Token::kEQ_STRICT) ? EQUAL : NOT_EQUAL; | 4469 BranchLabels labels = compiler->CreateBranchLabels(branch); |
| 4505 EmitBranchOnCondition(compiler, | 4470 |
| 4506 branch->true_successor(), | 4471 EmitStrictComparison(compiler, this, labels); |
| 4507 branch->false_successor(), | |
| 4508 true_condition); | |
| 4509 } | 4472 } |
| 4510 | 4473 |
| 4511 | 4474 |
| 4512 LocationSummary* ClosureCallInstr::MakeLocationSummary() const { | 4475 LocationSummary* ClosureCallInstr::MakeLocationSummary() const { |
| 4513 const intptr_t kNumInputs = 0; | 4476 const intptr_t kNumInputs = 0; |
| 4514 const intptr_t kNumTemps = 1; | 4477 const intptr_t kNumTemps = 1; |
| 4515 LocationSummary* result = | 4478 LocationSummary* result = |
| 4516 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 4479 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 4517 result->set_out(Location::RegisterLocation(RAX)); | 4480 result->set_out(Location::RegisterLocation(RAX)); |
| 4518 result->set_temp(0, Location::RegisterLocation(R10)); // Arg. descriptor. | 4481 result->set_temp(0, Location::RegisterLocation(R10)); // Arg. descriptor. |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4617 PcDescriptors::kOther, | 4580 PcDescriptors::kOther, |
| 4618 locs()); | 4581 locs()); |
| 4619 __ Drop(2); // Discard type arguments and receiver. | 4582 __ Drop(2); // Discard type arguments and receiver. |
| 4620 } | 4583 } |
| 4621 | 4584 |
| 4622 } // namespace dart | 4585 } // namespace dart |
| 4623 | 4586 |
| 4624 #undef __ | 4587 #undef __ |
| 4625 | 4588 |
| 4626 #endif // defined TARGET_ARCH_X64 | 4589 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |