| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 "lib/error.h" | 10 #include "lib/error.h" |
| (...skipping 345 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 356 LocationSummary* locs, | 356 LocationSummary* locs, |
| 357 BranchInstr* branch, | 357 BranchInstr* branch, |
| 358 Token::Kind kind, | 358 Token::Kind kind, |
| 359 intptr_t deopt_id, | 359 intptr_t deopt_id, |
| 360 intptr_t token_pos, | 360 intptr_t token_pos, |
| 361 intptr_t try_index) { | 361 intptr_t try_index) { |
| 362 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); | 362 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); |
| 363 const ICData& ic_data = ICData::Handle(orig_ic_data.AsUnaryClassChecks()); | 363 const ICData& ic_data = ICData::Handle(orig_ic_data.AsUnaryClassChecks()); |
| 364 ASSERT(ic_data.NumberOfChecks() > 0); | 364 ASSERT(ic_data.NumberOfChecks() > 0); |
| 365 ASSERT(ic_data.num_args_tested() == 1); | 365 ASSERT(ic_data.num_args_tested() == 1); |
| 366 Label* deopt = compiler->AddDeoptStub(deopt_id, try_index, kDeoptEquality); | 366 Label* deopt = compiler->AddDeoptStub(deopt_id, kDeoptEquality); |
| 367 Register left = locs->in(0).reg(); | 367 Register left = locs->in(0).reg(); |
| 368 Register right = locs->in(1).reg(); | 368 Register right = locs->in(1).reg(); |
| 369 __ testq(left, Immediate(kSmiTagMask)); | 369 __ testq(left, Immediate(kSmiTagMask)); |
| 370 Register temp = locs->temp(0).reg(); | 370 Register temp = locs->temp(0).reg(); |
| 371 if (ic_data.GetReceiverClassIdAt(0) == kSmiCid) { | 371 if (ic_data.GetReceiverClassIdAt(0) == kSmiCid) { |
| 372 Label done, load_class_id; | 372 Label done, load_class_id; |
| 373 __ j(NOT_ZERO, &load_class_id, Assembler::kNearJump); | 373 __ j(NOT_ZERO, &load_class_id, Assembler::kNearJump); |
| 374 __ movq(temp, Immediate(kSmiCid)); | 374 __ movq(temp, Immediate(kSmiCid)); |
| 375 __ jmp(&done, Assembler::kNearJump); | 375 __ jmp(&done, Assembler::kNearJump); |
| 376 __ Bind(&load_class_id); | 376 __ Bind(&load_class_id); |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 441 __ Bind(&done); | 441 __ Bind(&done); |
| 442 } | 442 } |
| 443 | 443 |
| 444 | 444 |
| 445 // Emit code when ICData's targets are all Object == (which is ===). | 445 // Emit code when ICData's targets are all Object == (which is ===). |
| 446 static void EmitCheckedStrictEqual(FlowGraphCompiler* compiler, | 446 static void EmitCheckedStrictEqual(FlowGraphCompiler* compiler, |
| 447 const ICData& ic_data, | 447 const ICData& ic_data, |
| 448 const LocationSummary& locs, | 448 const LocationSummary& locs, |
| 449 Token::Kind kind, | 449 Token::Kind kind, |
| 450 BranchInstr* branch, | 450 BranchInstr* branch, |
| 451 intptr_t deopt_id, | 451 intptr_t deopt_id) { |
| 452 intptr_t try_index) { | |
| 453 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); | 452 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); |
| 454 Register left = locs.in(0).reg(); | 453 Register left = locs.in(0).reg(); |
| 455 Register right = locs.in(1).reg(); | 454 Register right = locs.in(1).reg(); |
| 456 Register temp = locs.temp(0).reg(); | 455 Register temp = locs.temp(0).reg(); |
| 457 Label* deopt = compiler->AddDeoptStub(deopt_id, | 456 Label* deopt = compiler->AddDeoptStub(deopt_id, kDeoptEquality); |
| 458 try_index, | |
| 459 kDeoptEquality); | |
| 460 __ testq(left, Immediate(kSmiTagMask)); | 457 __ testq(left, Immediate(kSmiTagMask)); |
| 461 __ j(ZERO, deopt); | 458 __ j(ZERO, deopt); |
| 462 // 'left' is not Smi. | 459 // 'left' is not Smi. |
| 463 const Immediate raw_null = | 460 const Immediate raw_null = |
| 464 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 461 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 465 Label identity_compare; | 462 Label identity_compare; |
| 466 __ cmpq(right, raw_null); | 463 __ cmpq(right, raw_null); |
| 467 __ j(EQUAL, &identity_compare); | 464 __ j(EQUAL, &identity_compare); |
| 468 __ cmpq(left, raw_null); | 465 __ cmpq(left, raw_null); |
| 469 __ j(EQUAL, &identity_compare); | 466 __ j(EQUAL, &identity_compare); |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 542 EmitEqualityAsPolymorphicCall(compiler, ic_data, locs, branch, kind, | 539 EmitEqualityAsPolymorphicCall(compiler, ic_data, locs, branch, kind, |
| 543 deopt_id, token_pos, try_index); | 540 deopt_id, token_pos, try_index); |
| 544 __ Bind(&done); | 541 __ Bind(&done); |
| 545 } | 542 } |
| 546 | 543 |
| 547 | 544 |
| 548 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler, | 545 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler, |
| 549 const LocationSummary& locs, | 546 const LocationSummary& locs, |
| 550 Token::Kind kind, | 547 Token::Kind kind, |
| 551 BranchInstr* branch, | 548 BranchInstr* branch, |
| 552 intptr_t deopt_id, | 549 intptr_t deopt_id) { |
| 553 intptr_t try_index) { | |
| 554 Register left = locs.in(0).reg(); | 550 Register left = locs.in(0).reg(); |
| 555 Register right = locs.in(1).reg(); | 551 Register right = locs.in(1).reg(); |
| 556 const bool left_is_smi = (branch == NULL) ? | 552 const bool left_is_smi = (branch == NULL) ? |
| 557 false : (branch->left()->ResultCid() == kSmiCid); | 553 false : (branch->left()->ResultCid() == kSmiCid); |
| 558 const bool right_is_smi = (branch == NULL) ? | 554 const bool right_is_smi = (branch == NULL) ? |
| 559 false : (branch->right()->ResultCid() == kSmiCid); | 555 false : (branch->right()->ResultCid() == kSmiCid); |
| 560 if (!left_is_smi || !right_is_smi) { | 556 if (!left_is_smi || !right_is_smi) { |
| 561 Register temp = locs.temp(0).reg(); | 557 Register temp = locs.temp(0).reg(); |
| 562 Label* deopt = compiler->AddDeoptStub(deopt_id, | 558 Label* deopt = compiler->AddDeoptStub(deopt_id, kDeoptSmiCompareSmi); |
| 563 try_index, | |
| 564 kDeoptSmiCompareSmi); | |
| 565 __ movq(temp, left); | 559 __ movq(temp, left); |
| 566 __ orq(temp, right); | 560 __ orq(temp, right); |
| 567 __ testq(temp, Immediate(kSmiTagMask)); | 561 __ testq(temp, Immediate(kSmiTagMask)); |
| 568 __ j(NOT_ZERO, deopt); | 562 __ j(NOT_ZERO, deopt); |
| 569 } | 563 } |
| 570 | 564 |
| 571 Condition true_condition = TokenKindToSmiCondition(kind); | 565 Condition true_condition = TokenKindToSmiCondition(kind); |
| 572 __ cmpq(left, right); | 566 __ cmpq(left, right); |
| 573 | 567 |
| 574 if (branch != NULL) { | 568 if (branch != NULL) { |
| (...skipping 23 matching lines...) Expand all Loading... |
| 598 UNREACHABLE(); | 592 UNREACHABLE(); |
| 599 return OVERFLOW; | 593 return OVERFLOW; |
| 600 } | 594 } |
| 601 } | 595 } |
| 602 | 596 |
| 603 | 597 |
| 604 static void EmitDoubleComparisonOp(FlowGraphCompiler* compiler, | 598 static void EmitDoubleComparisonOp(FlowGraphCompiler* compiler, |
| 605 const LocationSummary& locs, | 599 const LocationSummary& locs, |
| 606 Token::Kind kind, | 600 Token::Kind kind, |
| 607 BranchInstr* branch, | 601 BranchInstr* branch, |
| 608 intptr_t deopt_id, | 602 intptr_t deopt_id) { |
| 609 intptr_t try_index) { | |
| 610 Register left = locs.in(0).reg(); | 603 Register left = locs.in(0).reg(); |
| 611 Register right = locs.in(1).reg(); | 604 Register right = locs.in(1).reg(); |
| 612 // TODO(srdjan): temp is only needed if a conversion Smi->Double occurs. | 605 // TODO(srdjan): temp is only needed if a conversion Smi->Double occurs. |
| 613 Register temp = locs.temp(0).reg(); | 606 Register temp = locs.temp(0).reg(); |
| 614 Label* deopt = compiler->AddDeoptStub(deopt_id, | 607 Label* deopt = compiler->AddDeoptStub(deopt_id, kDeoptDoubleComparison); |
| 615 try_index, | |
| 616 kDeoptDoubleComparison); | |
| 617 compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt); | 608 compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt); |
| 618 compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt); | 609 compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt); |
| 619 | 610 |
| 620 Condition true_condition = TokenKindToDoubleCondition(kind); | 611 Condition true_condition = TokenKindToDoubleCondition(kind); |
| 621 if (branch != NULL) { | 612 if (branch != NULL) { |
| 622 compiler->EmitDoubleCompareBranch( | 613 compiler->EmitDoubleCompareBranch( |
| 623 true_condition, XMM0, XMM1, branch); | 614 true_condition, XMM0, XMM1, branch); |
| 624 } else { | 615 } else { |
| 625 compiler->EmitDoubleCompareBool( | 616 compiler->EmitDoubleCompareBool( |
| 626 true_condition, XMM0, XMM1, locs.out().reg()); | 617 true_condition, XMM0, XMM1, locs.out().reg()); |
| 627 } | 618 } |
| 628 } | 619 } |
| 629 | 620 |
| 630 | 621 |
| 631 void EqualityCompareComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 622 void EqualityCompareComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 623 BranchInstr* kNoBranch = NULL; |
| 632 if (receiver_class_id() == kSmiCid) { | 624 if (receiver_class_id() == kSmiCid) { |
| 633 // Deoptimizes if both arguments not Smi. | 625 // Deoptimizes if both arguments not Smi. |
| 634 EmitSmiComparisonOp(compiler, *locs(), kind(), NULL, // No branch. | 626 EmitSmiComparisonOp(compiler, *locs(), kind(), kNoBranch, deopt_id()); |
| 635 deopt_id(), try_index()); | |
| 636 return; | 627 return; |
| 637 } | 628 } |
| 638 if (receiver_class_id() == kDoubleCid) { | 629 if (receiver_class_id() == kDoubleCid) { |
| 639 // Deoptimizes if both arguments are Smi, or if none is Double or Smi. | 630 // Deoptimizes if both arguments are Smi, or if none is Double or Smi. |
| 640 EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL, // No branch. | 631 EmitDoubleComparisonOp(compiler, *locs(), kind(), kNoBranch, deopt_id()); |
| 641 deopt_id(), try_index()); | |
| 642 return; | 632 return; |
| 643 } | 633 } |
| 644 const bool is_checked_strict_equal = | 634 const bool is_checked_strict_equal = |
| 645 HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid); | 635 HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid); |
| 646 if (is_checked_strict_equal) { | 636 if (is_checked_strict_equal) { |
| 647 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), NULL, | 637 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), kNoBranch, |
| 648 deopt_id(), try_index()); | 638 deopt_id()); |
| 649 return; | 639 return; |
| 650 } | 640 } |
| 651 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { | 641 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { |
| 652 EmitGenericEqualityCompare(compiler, locs(), kind(), NULL, *ic_data(), | 642 EmitGenericEqualityCompare(compiler, locs(), kind(), kNoBranch, *ic_data(), |
| 653 deopt_id(), token_pos(), try_index()); | 643 deopt_id(), token_pos(), try_index()); |
| 654 } else { | 644 } else { |
| 655 Register left = locs()->in(0).reg(); | 645 Register left = locs()->in(0).reg(); |
| 656 Register right = locs()->in(1).reg(); | 646 Register right = locs()->in(1).reg(); |
| 657 __ pushq(left); | 647 __ pushq(left); |
| 658 __ pushq(right); | 648 __ pushq(right); |
| 659 EmitEqualityAsInstanceCall(compiler, | 649 EmitEqualityAsInstanceCall(compiler, |
| 660 deopt_id(), | 650 deopt_id(), |
| 661 token_pos(), | 651 token_pos(), |
| 662 try_index(), | 652 try_index(), |
| (...skipping 22 matching lines...) Expand all Loading... |
| 685 // Pick arbitrary fixed input registers because this is a call. | 675 // Pick arbitrary fixed input registers because this is a call. |
| 686 locs->set_in(0, Location::RegisterLocation(RAX)); | 676 locs->set_in(0, Location::RegisterLocation(RAX)); |
| 687 locs->set_in(1, Location::RegisterLocation(RCX)); | 677 locs->set_in(1, Location::RegisterLocation(RCX)); |
| 688 locs->set_out(Location::RegisterLocation(RAX)); | 678 locs->set_out(Location::RegisterLocation(RAX)); |
| 689 return locs; | 679 return locs; |
| 690 } | 680 } |
| 691 | 681 |
| 692 | 682 |
| 693 void RelationalOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 683 void RelationalOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 694 if (operands_class_id() == kSmiCid) { | 684 if (operands_class_id() == kSmiCid) { |
| 695 EmitSmiComparisonOp(compiler, *locs(), kind(), NULL, | 685 EmitSmiComparisonOp(compiler, *locs(), kind(), NULL, deopt_id()); |
| 696 deopt_id(), try_index()); | |
| 697 return; | 686 return; |
| 698 } | 687 } |
| 699 if (operands_class_id() == kDoubleCid) { | 688 if (operands_class_id() == kDoubleCid) { |
| 700 EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL, | 689 EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL, deopt_id()); |
| 701 deopt_id(), try_index()); | |
| 702 return; | 690 return; |
| 703 } | 691 } |
| 704 | 692 |
| 705 // Push arguments for the call. | 693 // Push arguments for the call. |
| 706 // TODO(fschneider): Split this instruction into different types to avoid | 694 // TODO(fschneider): Split this instruction into different types to avoid |
| 707 // explicitly pushing arguments to the call here. | 695 // explicitly pushing arguments to the call here. |
| 708 Register left = locs()->in(0).reg(); | 696 Register left = locs()->in(0).reg(); |
| 709 Register right = locs()->in(1).reg(); | 697 Register right = locs()->in(1).reg(); |
| 710 __ pushq(left); | 698 __ pushq(left); |
| 711 __ pushq(right); | 699 __ pushq(right); |
| 712 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { | 700 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { |
| 713 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 701 Label* deopt = compiler->AddDeoptStub(deopt_id(), kDeoptRelationalOp); |
| 714 try_index(), | |
| 715 kDeoptRelationalOp); | |
| 716 | 702 |
| 717 // Load class into RDI. Since this is a call, any register except | 703 // Load class into RDI. Since this is a call, any register except |
| 718 // the fixed input registers would be ok. | 704 // the fixed input registers would be ok. |
| 719 ASSERT((left != RDI) && (right != RDI)); | 705 ASSERT((left != RDI) && (right != RDI)); |
| 720 Label done; | 706 Label done; |
| 721 __ movq(RDI, Immediate(kSmiCid)); | 707 __ movq(RDI, Immediate(kSmiCid)); |
| 722 __ testq(left, Immediate(kSmiTagMask)); | 708 __ testq(left, Immediate(kSmiTagMask)); |
| 723 __ j(ZERO, &done); | 709 __ j(ZERO, &done); |
| 724 __ LoadClassId(RDI, left); | 710 __ LoadClassId(RDI, left); |
| 725 __ Bind(&done); | 711 __ Bind(&done); |
| (...skipping 369 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1095 LocationSummary::kNoCall); | 1081 LocationSummary::kNoCall); |
| 1096 } | 1082 } |
| 1097 | 1083 |
| 1098 | 1084 |
| 1099 void LoadVMFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1085 void LoadVMFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1100 Register instance_reg = locs()->in(0).reg(); | 1086 Register instance_reg = locs()->in(0).reg(); |
| 1101 Register result_reg = locs()->out().reg(); | 1087 Register result_reg = locs()->out().reg(); |
| 1102 if (HasICData()) { | 1088 if (HasICData()) { |
| 1103 ASSERT(original() != NULL); | 1089 ASSERT(original() != NULL); |
| 1104 Label* deopt = compiler->AddDeoptStub(original()->deopt_id(), | 1090 Label* deopt = compiler->AddDeoptStub(original()->deopt_id(), |
| 1105 original()->try_index(), | |
| 1106 kDeoptInstanceGetterSameTarget); | 1091 kDeoptInstanceGetterSameTarget); |
| 1107 // Smis do not have instance fields (Smi class is always first). | 1092 // Smis do not have instance fields (Smi class is always first). |
| 1108 // Use 'result' as temporary register. | 1093 // Use 'result' as temporary register. |
| 1109 ASSERT(result_reg != instance_reg); | 1094 ASSERT(result_reg != instance_reg); |
| 1110 ASSERT(ic_data() != NULL); | 1095 ASSERT(ic_data() != NULL); |
| 1111 compiler->EmitClassChecksNoSmi(*ic_data(), instance_reg, result_reg, deopt); | 1096 compiler->EmitClassChecksNoSmi(*ic_data(), instance_reg, result_reg, deopt); |
| 1112 } | 1097 } |
| 1113 | 1098 |
| 1114 __ movq(result_reg, FieldAddress(instance_reg, offset_in_bytes())); | 1099 __ movq(result_reg, FieldAddress(instance_reg, offset_in_bytes())); |
| 1115 } | 1100 } |
| (...skipping 361 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1477 ASSERT(left == result); | 1462 ASSERT(left == result); |
| 1478 Label* deopt = NULL; | 1463 Label* deopt = NULL; |
| 1479 switch (op_kind()) { | 1464 switch (op_kind()) { |
| 1480 case Token::kBIT_AND: | 1465 case Token::kBIT_AND: |
| 1481 case Token::kBIT_OR: | 1466 case Token::kBIT_OR: |
| 1482 case Token::kBIT_XOR: | 1467 case Token::kBIT_XOR: |
| 1483 // Can't deoptimize. Arguments are already checked for smi. | 1468 // Can't deoptimize. Arguments are already checked for smi. |
| 1484 break; | 1469 break; |
| 1485 default: | 1470 default: |
| 1486 deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), | 1471 deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), |
| 1487 instance_call()->try_index(), | |
| 1488 kDeoptBinarySmiOp); | 1472 kDeoptBinarySmiOp); |
| 1489 } | 1473 } |
| 1490 switch (op_kind()) { | 1474 switch (op_kind()) { |
| 1491 case Token::kADD: { | 1475 case Token::kADD: { |
| 1492 __ addq(left, right); | 1476 __ addq(left, right); |
| 1493 __ j(OVERFLOW, deopt); | 1477 __ j(OVERFLOW, deopt); |
| 1494 break; | 1478 break; |
| 1495 } | 1479 } |
| 1496 case Token::kSUB: { | 1480 case Token::kSUB: { |
| 1497 __ subq(left, right); | 1481 __ subq(left, right); |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1643 // TODO(regis): For now, we only support Token::kBIT_AND for a Mint or Smi | 1627 // TODO(regis): For now, we only support Token::kBIT_AND for a Mint or Smi |
| 1644 // receiver and a Mint or Smi argument. We fall back to the run time call if | 1628 // receiver and a Mint or Smi argument. We fall back to the run time call if |
| 1645 // both receiver and argument are Mint or if one of them is Mint and the other | 1629 // both receiver and argument are Mint or if one of them is Mint and the other |
| 1646 // is a negative Smi. | 1630 // is a negative Smi. |
| 1647 Register left = locs()->in(0).reg(); | 1631 Register left = locs()->in(0).reg(); |
| 1648 Register right = locs()->in(1).reg(); | 1632 Register right = locs()->in(1).reg(); |
| 1649 Register result = locs()->out().reg(); | 1633 Register result = locs()->out().reg(); |
| 1650 ASSERT(left == result); | 1634 ASSERT(left == result); |
| 1651 ASSERT(op_kind() == Token::kBIT_AND); | 1635 ASSERT(op_kind() == Token::kBIT_AND); |
| 1652 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), | 1636 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), |
| 1653 instance_call()->try_index(), | |
| 1654 kDeoptBinaryMintOp); | 1637 kDeoptBinaryMintOp); |
| 1655 Label mint_static_call, smi_static_call, non_smi, smi_smi, done; | 1638 Label mint_static_call, smi_static_call, non_smi, smi_smi, done; |
| 1656 __ testq(left, Immediate(kSmiTagMask)); // Is receiver Smi? | 1639 __ testq(left, Immediate(kSmiTagMask)); // Is receiver Smi? |
| 1657 __ j(NOT_ZERO, &non_smi); | 1640 __ j(NOT_ZERO, &non_smi); |
| 1658 __ testq(right, Immediate(kSmiTagMask)); // Is argument Smi? | 1641 __ testq(right, Immediate(kSmiTagMask)); // Is argument Smi? |
| 1659 __ j(ZERO, &smi_smi); | 1642 __ j(ZERO, &smi_smi); |
| 1660 __ CompareClassId(right, kMintCid); // Is argument Mint? | 1643 __ CompareClassId(right, kMintCid); // Is argument Mint? |
| 1661 __ j(NOT_EQUAL, deopt); // Argument neither Smi nor Mint. | 1644 __ j(NOT_EQUAL, deopt); // Argument neither Smi nor Mint. |
| 1662 __ cmpq(left, Immediate(0)); | 1645 __ cmpq(left, Immediate(0)); |
| 1663 __ j(LESS, &smi_static_call); // Negative Smi receiver, Mint argument. | 1646 __ j(LESS, &smi_static_call); // Negative Smi receiver, Mint argument. |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1750 instance_call()->try_index(), | 1733 instance_call()->try_index(), |
| 1751 &label, | 1734 &label, |
| 1752 PcDescriptors::kOther, | 1735 PcDescriptors::kOther, |
| 1753 locs()); | 1736 locs()); |
| 1754 // Newly allocated object is now in the result register (RAX). | 1737 // Newly allocated object is now in the result register (RAX). |
| 1755 ASSERT(result == RAX); | 1738 ASSERT(result == RAX); |
| 1756 __ movq(right, Address(RSP, 0)); | 1739 __ movq(right, Address(RSP, 0)); |
| 1757 __ movq(left, Address(RSP, kWordSize)); | 1740 __ movq(left, Address(RSP, kWordSize)); |
| 1758 | 1741 |
| 1759 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), | 1742 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), |
| 1760 instance_call()->try_index(), | |
| 1761 kDeoptBinaryDoubleOp); | 1743 kDeoptBinaryDoubleOp); |
| 1762 | 1744 |
| 1763 // Binary operation of two Smi's produces a Smi not a double. | 1745 // Binary operation of two Smi's produces a Smi not a double. |
| 1764 __ movq(temp, left); | 1746 __ movq(temp, left); |
| 1765 __ orq(temp, right); | 1747 __ orq(temp, right); |
| 1766 __ testq(temp, Immediate(kSmiTagMask)); | 1748 __ testq(temp, Immediate(kSmiTagMask)); |
| 1767 __ j(ZERO, deopt); | 1749 __ j(ZERO, deopt); |
| 1768 | 1750 |
| 1769 compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt); | 1751 compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt); |
| 1770 compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt); | 1752 compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 1792 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1774 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1793 summary->set_in(0, Location::RequiresRegister()); | 1775 summary->set_in(0, Location::RequiresRegister()); |
| 1794 summary->set_in(1, Location::RequiresRegister()); | 1776 summary->set_in(1, Location::RequiresRegister()); |
| 1795 summary->set_temp(0, Location::RequiresRegister()); | 1777 summary->set_temp(0, Location::RequiresRegister()); |
| 1796 return summary; | 1778 return summary; |
| 1797 } | 1779 } |
| 1798 | 1780 |
| 1799 | 1781 |
| 1800 void CheckEitherNonSmiComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1782 void CheckEitherNonSmiComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1801 Label* deopt = compiler->AddDeoptStub(instance_call_->deopt_id(), | 1783 Label* deopt = compiler->AddDeoptStub(instance_call_->deopt_id(), |
| 1802 instance_call_->try_index(), | |
| 1803 kDeoptBinaryDoubleOp); | 1784 kDeoptBinaryDoubleOp); |
| 1804 | 1785 |
| 1805 Register temp = locs()->temp(0).reg(); | 1786 Register temp = locs()->temp(0).reg(); |
| 1806 __ movq(temp, locs()->in(0).reg()); | 1787 __ movq(temp, locs()->in(0).reg()); |
| 1807 __ orq(temp, locs()->in(1).reg()); | 1788 __ orq(temp, locs()->in(1).reg()); |
| 1808 __ testl(temp, Immediate(kSmiTagMask)); | 1789 __ testl(temp, Immediate(kSmiTagMask)); |
| 1809 __ j(ZERO, deopt); | 1790 __ j(ZERO, deopt); |
| 1810 } | 1791 } |
| 1811 | 1792 |
| 1812 | 1793 |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1888 } | 1869 } |
| 1889 | 1870 |
| 1890 | 1871 |
| 1891 void UnboxDoubleComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1872 void UnboxDoubleComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1892 const intptr_t v_cid = value()->ResultCid(); | 1873 const intptr_t v_cid = value()->ResultCid(); |
| 1893 | 1874 |
| 1894 const Register value = locs()->in(0).reg(); | 1875 const Register value = locs()->in(0).reg(); |
| 1895 const XmmRegister result = locs()->out().xmm_reg(); | 1876 const XmmRegister result = locs()->out().xmm_reg(); |
| 1896 if (v_cid != kDoubleCid) { | 1877 if (v_cid != kDoubleCid) { |
| 1897 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), | 1878 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), |
| 1898 instance_call()->try_index(), | |
| 1899 kDeoptBinaryDoubleOp); | 1879 kDeoptBinaryDoubleOp); |
| 1900 compiler->LoadDoubleOrSmiToXmm(result, | 1880 compiler->LoadDoubleOrSmiToXmm(result, |
| 1901 value, | 1881 value, |
| 1902 locs()->temp(0).reg(), | 1882 locs()->temp(0).reg(), |
| 1903 deopt); | 1883 deopt); |
| 1904 } else { | 1884 } else { |
| 1905 __ movsd(result, FieldAddress(value, Double::value_offset())); | 1885 __ movsd(result, FieldAddress(value, Double::value_offset())); |
| 1906 } | 1886 } |
| 1907 } | 1887 } |
| 1908 | 1888 |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1945 return summary; | 1925 return summary; |
| 1946 } | 1926 } |
| 1947 | 1927 |
| 1948 | 1928 |
| 1949 void UnarySmiOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1929 void UnarySmiOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1950 Register value = locs()->in(0).reg(); | 1930 Register value = locs()->in(0).reg(); |
| 1951 ASSERT(value == locs()->out().reg()); | 1931 ASSERT(value == locs()->out().reg()); |
| 1952 switch (op_kind()) { | 1932 switch (op_kind()) { |
| 1953 case Token::kNEGATE: { | 1933 case Token::kNEGATE: { |
| 1954 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), | 1934 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), |
| 1955 instance_call()->try_index(), | |
| 1956 kDeoptUnaryOp); | 1935 kDeoptUnaryOp); |
| 1957 __ negq(value); | 1936 __ negq(value); |
| 1958 __ j(OVERFLOW, deopt); | 1937 __ j(OVERFLOW, deopt); |
| 1959 break; | 1938 break; |
| 1960 } | 1939 } |
| 1961 case Token::kBIT_NOT: | 1940 case Token::kBIT_NOT: |
| 1962 __ notq(value); | 1941 __ notq(value); |
| 1963 __ andq(value, Immediate(~kSmiTagMask)); // Remove inverted smi-tag. | 1942 __ andq(value, Immediate(~kSmiTagMask)); // Remove inverted smi-tag. |
| 1964 break; | 1943 break; |
| 1965 default: | 1944 default: |
| (...skipping 22 matching lines...) Expand all Loading... |
| 1988 // TODO(srdjan): Implement for more checks. | 1967 // TODO(srdjan): Implement for more checks. |
| 1989 ASSERT(ic_data.NumberOfChecks() == 1); | 1968 ASSERT(ic_data.NumberOfChecks() == 1); |
| 1990 intptr_t test_class_id; | 1969 intptr_t test_class_id; |
| 1991 Function& target = Function::Handle(); | 1970 Function& target = Function::Handle(); |
| 1992 ic_data.GetOneClassCheckAt(0, &test_class_id, &target); | 1971 ic_data.GetOneClassCheckAt(0, &test_class_id, &target); |
| 1993 | 1972 |
| 1994 Register value = locs()->in(0).reg(); | 1973 Register value = locs()->in(0).reg(); |
| 1995 Register result = locs()->out().reg(); | 1974 Register result = locs()->out().reg(); |
| 1996 ASSERT(value == result); | 1975 ASSERT(value == result); |
| 1997 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), | 1976 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), |
| 1998 instance_call()->try_index(), | |
| 1999 kDeoptUnaryOp); | 1977 kDeoptUnaryOp); |
| 2000 if (test_class_id == kDoubleCid) { | 1978 if (test_class_id == kDoubleCid) { |
| 2001 Register temp = locs()->temp(0).reg(); | 1979 Register temp = locs()->temp(0).reg(); |
| 2002 __ testq(value, Immediate(kSmiTagMask)); | 1980 __ testq(value, Immediate(kSmiTagMask)); |
| 2003 __ j(ZERO, deopt); // Smi. | 1981 __ j(ZERO, deopt); // Smi. |
| 2004 __ CompareClassId(value, kDoubleCid); | 1982 __ CompareClassId(value, kDoubleCid); |
| 2005 __ j(NOT_EQUAL, deopt); | 1983 __ j(NOT_EQUAL, deopt); |
| 2006 // Allocate result object. | 1984 // Allocate result object. |
| 2007 const Class& double_class = compiler->double_class(); | 1985 const Class& double_class = compiler->double_class(); |
| 2008 const Code& stub = | 1986 const Code& stub = |
| (...skipping 28 matching lines...) Expand all Loading... |
| 2037 locs->set_out(Location::SameAsFirstInput()); | 2015 locs->set_out(Location::SameAsFirstInput()); |
| 2038 return locs; | 2016 return locs; |
| 2039 } | 2017 } |
| 2040 | 2018 |
| 2041 | 2019 |
| 2042 void DoubleToDoubleComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 2020 void DoubleToDoubleComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2043 Register value = locs()->in(0).reg(); | 2021 Register value = locs()->in(0).reg(); |
| 2044 Register result = locs()->out().reg(); | 2022 Register result = locs()->out().reg(); |
| 2045 | 2023 |
| 2046 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), | 2024 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), |
| 2047 instance_call()->try_index(), | |
| 2048 kDeoptDoubleToDouble); | 2025 kDeoptDoubleToDouble); |
| 2049 | 2026 |
| 2050 __ testq(value, Immediate(kSmiTagMask)); | 2027 __ testq(value, Immediate(kSmiTagMask)); |
| 2051 __ j(ZERO, deopt); // Deoptimize if Smi. | 2028 __ j(ZERO, deopt); // Deoptimize if Smi. |
| 2052 __ CompareClassId(value, kDoubleCid); | 2029 __ CompareClassId(value, kDoubleCid); |
| 2053 __ j(NOT_EQUAL, deopt); // Deoptimize if not Double. | 2030 __ j(NOT_EQUAL, deopt); // Deoptimize if not Double. |
| 2054 ASSERT(value == result); | 2031 ASSERT(value == result); |
| 2055 } | 2032 } |
| 2056 | 2033 |
| 2057 | 2034 |
| 2058 LocationSummary* SmiToDoubleComp::MakeLocationSummary() const { | 2035 LocationSummary* SmiToDoubleComp::MakeLocationSummary() const { |
| 2059 return MakeCallSummary(); // Calls a stub to allocate result. | 2036 return MakeCallSummary(); // Calls a stub to allocate result. |
| 2060 } | 2037 } |
| 2061 | 2038 |
| 2062 | 2039 |
| 2063 void SmiToDoubleComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 2040 void SmiToDoubleComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2064 Register result = locs()->out().reg(); | 2041 Register result = locs()->out().reg(); |
| 2065 | 2042 |
| 2066 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), | 2043 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), |
| 2067 instance_call()->try_index(), | |
| 2068 kDeoptIntegerToDouble); | 2044 kDeoptIntegerToDouble); |
| 2069 | 2045 |
| 2070 const Class& double_class = compiler->double_class(); | 2046 const Class& double_class = compiler->double_class(); |
| 2071 const Code& stub = | 2047 const Code& stub = |
| 2072 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); | 2048 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); |
| 2073 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); | 2049 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); |
| 2074 | 2050 |
| 2075 // TODO(fschneider): Inline new-space allocation and move the call into | 2051 // TODO(fschneider): Inline new-space allocation and move the call into |
| 2076 // deferred code. | 2052 // deferred code. |
| 2077 compiler->GenerateCall(instance_call()->token_pos(), | 2053 compiler->GenerateCall(instance_call()->token_pos(), |
| (...skipping 15 matching lines...) Expand all Loading... |
| 2093 } | 2069 } |
| 2094 | 2070 |
| 2095 | 2071 |
| 2096 LocationSummary* PolymorphicInstanceCallComp::MakeLocationSummary() const { | 2072 LocationSummary* PolymorphicInstanceCallComp::MakeLocationSummary() const { |
| 2097 return MakeCallSummary(); | 2073 return MakeCallSummary(); |
| 2098 } | 2074 } |
| 2099 | 2075 |
| 2100 | 2076 |
| 2101 void PolymorphicInstanceCallComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 2077 void PolymorphicInstanceCallComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2102 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), | 2078 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), |
| 2103 instance_call()->try_index(), | |
| 2104 kDeoptPolymorphicInstanceCallTestFail); | 2079 kDeoptPolymorphicInstanceCallTestFail); |
| 2105 if (!HasICData() || (ic_data()->NumberOfChecks() == 0)) { | 2080 if (!HasICData() || (ic_data()->NumberOfChecks() == 0)) { |
| 2106 __ jmp(deopt); | 2081 __ jmp(deopt); |
| 2107 return; | 2082 return; |
| 2108 } | 2083 } |
| 2109 ASSERT(HasICData()); | 2084 ASSERT(HasICData()); |
| 2110 ASSERT(ic_data()->num_args_tested() == 1); | 2085 ASSERT(ic_data()->num_args_tested() == 1); |
| 2111 if (!with_checks()) { | 2086 if (!with_checks()) { |
| 2112 const Function& target = Function::ZoneHandle(ic_data()->GetTargetAt(0)); | 2087 const Function& target = Function::ZoneHandle(ic_data()->GetTargetAt(0)); |
| 2113 compiler->GenerateStaticCall(instance_call()->deopt_id(), | 2088 compiler->GenerateStaticCall(instance_call()->deopt_id(), |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2194 locs->set_in(0, Location::RegisterLocation(RAX)); | 2169 locs->set_in(0, Location::RegisterLocation(RAX)); |
| 2195 locs->set_in(1, Location::RegisterLocation(RCX)); | 2170 locs->set_in(1, Location::RegisterLocation(RCX)); |
| 2196 return locs; | 2171 return locs; |
| 2197 } | 2172 } |
| 2198 | 2173 |
| 2199 | 2174 |
| 2200 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2175 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2201 // Relational or equality. | 2176 // Relational or equality. |
| 2202 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { | 2177 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { |
| 2203 if (ICDataWithBothClassIds(*ic_data(), kSmiCid)) { | 2178 if (ICDataWithBothClassIds(*ic_data(), kSmiCid)) { |
| 2204 EmitSmiComparisonOp(compiler, *locs(), kind(), this, | 2179 EmitSmiComparisonOp(compiler, *locs(), kind(), this, deopt_id()); |
| 2205 deopt_id(), try_index()); | |
| 2206 return; | 2180 return; |
| 2207 } | 2181 } |
| 2208 if (ICDataWithBothClassIds(*ic_data(), kDoubleCid)) { | 2182 if (ICDataWithBothClassIds(*ic_data(), kDoubleCid)) { |
| 2209 EmitDoubleComparisonOp(compiler, *locs(), kind(), this, | 2183 EmitDoubleComparisonOp(compiler, *locs(), kind(), this, deopt_id()); |
| 2210 deopt_id(), try_index()); | |
| 2211 return; | 2184 return; |
| 2212 } | 2185 } |
| 2213 if (IsCheckedStrictEquals(*ic_data(), kind())) { | 2186 if (IsCheckedStrictEquals(*ic_data(), kind())) { |
| 2214 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), this, | 2187 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), this, |
| 2215 deopt_id(), try_index()); | 2188 deopt_id()); |
| 2216 return; | 2189 return; |
| 2217 } | 2190 } |
| 2218 // TODO(srdjan): Add Smi/Double, Double/Smi comparisons. | 2191 // TODO(srdjan): Add Smi/Double, Double/Smi comparisons. |
| 2219 if ((kind() == Token::kEQ) || (kind() == Token::kNE)) { | 2192 if ((kind() == Token::kEQ) || (kind() == Token::kNE)) { |
| 2220 EmitGenericEqualityCompare(compiler, locs(), kind(), this, *ic_data(), | 2193 EmitGenericEqualityCompare(compiler, locs(), kind(), this, *ic_data(), |
| 2221 deopt_id(), token_pos(), try_index()); | 2194 deopt_id(), token_pos(), try_index()); |
| 2222 return; | 2195 return; |
| 2223 } | 2196 } |
| 2224 // Otherwise polymorphic dispatch? | 2197 // Otherwise polymorphic dispatch? |
| 2225 } | 2198 } |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2286 summary->set_in(0, Location::RequiresRegister()); | 2259 summary->set_in(0, Location::RequiresRegister()); |
| 2287 summary->set_temp(0, Location::RequiresRegister()); | 2260 summary->set_temp(0, Location::RequiresRegister()); |
| 2288 return summary; | 2261 return summary; |
| 2289 } | 2262 } |
| 2290 | 2263 |
| 2291 | 2264 |
| 2292 void CheckClassComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 2265 void CheckClassComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2293 Register value = locs()->in(0).reg(); | 2266 Register value = locs()->in(0).reg(); |
| 2294 Register temp = locs()->temp(0).reg(); | 2267 Register temp = locs()->temp(0).reg(); |
| 2295 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 2268 Label* deopt = compiler->AddDeoptStub(deopt_id(), |
| 2296 try_index(), | |
| 2297 kDeoptCheckClass); | 2269 kDeoptCheckClass); |
| 2298 ASSERT(ic_data()->GetReceiverClassIdAt(0) != kSmiCid); | 2270 ASSERT(ic_data()->GetReceiverClassIdAt(0) != kSmiCid); |
| 2299 __ testq(value, Immediate(kSmiTagMask)); | 2271 __ testq(value, Immediate(kSmiTagMask)); |
| 2300 __ j(ZERO, deopt); | 2272 __ j(ZERO, deopt); |
| 2301 __ LoadClassId(temp, value); | 2273 __ LoadClassId(temp, value); |
| 2302 Label is_ok; | 2274 Label is_ok; |
| 2303 const intptr_t num_checks = ic_data()->NumberOfChecks(); | 2275 const intptr_t num_checks = ic_data()->NumberOfChecks(); |
| 2304 const bool use_near_jump = num_checks < 5; | 2276 const bool use_near_jump = num_checks < 5; |
| 2305 for (intptr_t i = 0; i < num_checks; i++) { | 2277 for (intptr_t i = 0; i < num_checks; i++) { |
| 2306 __ cmpl(temp, Immediate(ic_data()->GetReceiverClassIdAt(i))); | 2278 __ cmpl(temp, Immediate(ic_data()->GetReceiverClassIdAt(i))); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 2324 LocationSummary* summary = | 2296 LocationSummary* summary = |
| 2325 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2297 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 2326 summary->set_in(0, Location::RequiresRegister()); | 2298 summary->set_in(0, Location::RequiresRegister()); |
| 2327 return summary; | 2299 return summary; |
| 2328 } | 2300 } |
| 2329 | 2301 |
| 2330 | 2302 |
| 2331 void CheckSmiComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 2303 void CheckSmiComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2332 Register value = locs()->in(0).reg(); | 2304 Register value = locs()->in(0).reg(); |
| 2333 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 2305 Label* deopt = compiler->AddDeoptStub(deopt_id(), |
| 2334 try_index(), | |
| 2335 kDeoptCheckSmi); | 2306 kDeoptCheckSmi); |
| 2336 __ testq(value, Immediate(kSmiTagMask)); | 2307 __ testq(value, Immediate(kSmiTagMask)); |
| 2337 __ j(NOT_ZERO, deopt); | 2308 __ j(NOT_ZERO, deopt); |
| 2338 } | 2309 } |
| 2339 | 2310 |
| 2340 | 2311 |
| 2341 LocationSummary* CheckArrayBoundComp::MakeLocationSummary() const { | 2312 LocationSummary* CheckArrayBoundComp::MakeLocationSummary() const { |
| 2342 return LocationSummary::Make(2, | 2313 return LocationSummary::Make(2, |
| 2343 Location::NoLocation(), | 2314 Location::NoLocation(), |
| 2344 LocationSummary::kNoCall); | 2315 LocationSummary::kNoCall); |
| 2345 } | 2316 } |
| 2346 | 2317 |
| 2347 | 2318 |
| 2348 void CheckArrayBoundComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 2319 void CheckArrayBoundComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2349 Register receiver = locs()->in(0).reg(); | 2320 Register receiver = locs()->in(0).reg(); |
| 2350 Register index = locs()->in(1).reg(); | 2321 Register index = locs()->in(1).reg(); |
| 2351 | 2322 |
| 2352 const DeoptReasonId deopt_reason = | 2323 const DeoptReasonId deopt_reason = |
| 2353 (array_type() == kGrowableObjectArrayCid) ? | 2324 (array_type() == kGrowableObjectArrayCid) ? |
| 2354 kDeoptLoadIndexedGrowableArray : kDeoptLoadIndexedFixedArray; | 2325 kDeoptLoadIndexedGrowableArray : kDeoptLoadIndexedFixedArray; |
| 2355 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 2326 Label* deopt = compiler->AddDeoptStub(deopt_id(), |
| 2356 try_index(), | |
| 2357 deopt_reason); | 2327 deopt_reason); |
| 2358 switch (array_type()) { | 2328 switch (array_type()) { |
| 2359 case kArrayCid: | 2329 case kArrayCid: |
| 2360 case kImmutableArrayCid: | 2330 case kImmutableArrayCid: |
| 2361 __ cmpq(index, FieldAddress(receiver, Array::length_offset())); | 2331 __ cmpq(index, FieldAddress(receiver, Array::length_offset())); |
| 2362 break; | 2332 break; |
| 2363 case kGrowableObjectArrayCid: | 2333 case kGrowableObjectArrayCid: |
| 2364 __ cmpq(index, | 2334 __ cmpq(index, |
| 2365 FieldAddress(receiver, GrowableObjectArray::length_offset())); | 2335 FieldAddress(receiver, GrowableObjectArray::length_offset())); |
| 2366 break; | 2336 break; |
| 2367 } | 2337 } |
| 2368 __ j(ABOVE_EQUAL, deopt); | 2338 __ j(ABOVE_EQUAL, deopt); |
| 2369 } | 2339 } |
| 2370 | 2340 |
| 2371 | 2341 |
| 2372 } // namespace dart | 2342 } // namespace dart |
| 2373 | 2343 |
| 2374 #undef __ | 2344 #undef __ |
| 2375 | 2345 |
| 2376 #endif // defined TARGET_ARCH_X64 | 2346 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |