| 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_IA32. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32. |
| 6 #if defined(TARGET_ARCH_IA32) | 6 #if defined(TARGET_ARCH_IA32) |
| 7 | 7 |
| 8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
| 9 | 9 |
| 10 #include "lib/error.h" | 10 #include "lib/error.h" |
| (...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 347 LocationSummary* locs, | 347 LocationSummary* locs, |
| 348 BranchInstr* branch, | 348 BranchInstr* branch, |
| 349 Token::Kind kind, | 349 Token::Kind kind, |
| 350 intptr_t deopt_id, | 350 intptr_t deopt_id, |
| 351 intptr_t token_pos, | 351 intptr_t token_pos, |
| 352 intptr_t try_index) { | 352 intptr_t try_index) { |
| 353 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); | 353 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); |
| 354 const ICData& ic_data = ICData::Handle(orig_ic_data.AsUnaryClassChecks()); | 354 const ICData& ic_data = ICData::Handle(orig_ic_data.AsUnaryClassChecks()); |
| 355 ASSERT(ic_data.NumberOfChecks() > 0); | 355 ASSERT(ic_data.NumberOfChecks() > 0); |
| 356 ASSERT(ic_data.num_args_tested() == 1); | 356 ASSERT(ic_data.num_args_tested() == 1); |
| 357 Label* deopt = compiler->AddDeoptStub(deopt_id, try_index, kDeoptEquality); | 357 Label* deopt = compiler->AddDeoptStub(deopt_id, kDeoptEquality); |
| 358 Register left = locs->in(0).reg(); | 358 Register left = locs->in(0).reg(); |
| 359 Register right = locs->in(1).reg(); | 359 Register right = locs->in(1).reg(); |
| 360 __ testl(left, Immediate(kSmiTagMask)); | 360 __ testl(left, Immediate(kSmiTagMask)); |
| 361 Register temp = locs->temp(0).reg(); | 361 Register temp = locs->temp(0).reg(); |
| 362 if (ic_data.GetReceiverClassIdAt(0) == kSmiCid) { | 362 if (ic_data.GetReceiverClassIdAt(0) == kSmiCid) { |
| 363 Label done, load_class_id; | 363 Label done, load_class_id; |
| 364 __ j(NOT_ZERO, &load_class_id, Assembler::kNearJump); | 364 __ j(NOT_ZERO, &load_class_id, Assembler::kNearJump); |
| 365 __ movl(temp, Immediate(kSmiCid)); | 365 __ movl(temp, Immediate(kSmiCid)); |
| 366 __ jmp(&done, Assembler::kNearJump); | 366 __ jmp(&done, Assembler::kNearJump); |
| 367 __ Bind(&load_class_id); | 367 __ Bind(&load_class_id); |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 431 __ Bind(&done); | 431 __ Bind(&done); |
| 432 } | 432 } |
| 433 | 433 |
| 434 | 434 |
| 435 // Emit code when ICData's targets are all Object == (which is ===). | 435 // Emit code when ICData's targets are all Object == (which is ===). |
| 436 static void EmitCheckedStrictEqual(FlowGraphCompiler* compiler, | 436 static void EmitCheckedStrictEqual(FlowGraphCompiler* compiler, |
| 437 const ICData& ic_data, | 437 const ICData& ic_data, |
| 438 const LocationSummary& locs, | 438 const LocationSummary& locs, |
| 439 Token::Kind kind, | 439 Token::Kind kind, |
| 440 BranchInstr* branch, | 440 BranchInstr* branch, |
| 441 intptr_t deopt_id, | 441 intptr_t deopt_id) { |
| 442 intptr_t try_index) { | |
| 443 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); | 442 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); |
| 444 Register left = locs.in(0).reg(); | 443 Register left = locs.in(0).reg(); |
| 445 Register right = locs.in(1).reg(); | 444 Register right = locs.in(1).reg(); |
| 446 Register temp = locs.temp(0).reg(); | 445 Register temp = locs.temp(0).reg(); |
| 447 Label* deopt = compiler->AddDeoptStub(deopt_id, | 446 Label* deopt = compiler->AddDeoptStub(deopt_id, kDeoptEquality); |
| 448 try_index, | |
| 449 kDeoptEquality); | |
| 450 __ testl(left, Immediate(kSmiTagMask)); | 447 __ testl(left, Immediate(kSmiTagMask)); |
| 451 __ j(ZERO, deopt); | 448 __ j(ZERO, deopt); |
| 452 // 'left' is not Smi. | 449 // 'left' is not Smi. |
| 453 const Immediate raw_null = | 450 const Immediate raw_null = |
| 454 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 451 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 455 Label identity_compare; | 452 Label identity_compare; |
| 456 __ cmpl(right, raw_null); | 453 __ cmpl(right, raw_null); |
| 457 __ j(EQUAL, &identity_compare); | 454 __ j(EQUAL, &identity_compare); |
| 458 __ cmpl(left, raw_null); | 455 __ cmpl(left, raw_null); |
| 459 __ j(EQUAL, &identity_compare); | 456 __ j(EQUAL, &identity_compare); |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 532 EmitEqualityAsPolymorphicCall(compiler, ic_data, locs, branch, kind, | 529 EmitEqualityAsPolymorphicCall(compiler, ic_data, locs, branch, kind, |
| 533 deopt_id, token_pos, try_index); | 530 deopt_id, token_pos, try_index); |
| 534 __ Bind(&done); | 531 __ Bind(&done); |
| 535 } | 532 } |
| 536 | 533 |
| 537 | 534 |
| 538 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler, | 535 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler, |
| 539 const LocationSummary& locs, | 536 const LocationSummary& locs, |
| 540 Token::Kind kind, | 537 Token::Kind kind, |
| 541 BranchInstr* branch, | 538 BranchInstr* branch, |
| 542 intptr_t deopt_id, | 539 intptr_t deopt_id) { |
| 543 intptr_t try_index) { | |
| 544 Register left = locs.in(0).reg(); | 540 Register left = locs.in(0).reg(); |
| 545 Register right = locs.in(1).reg(); | 541 Register right = locs.in(1).reg(); |
| 546 const bool left_is_smi = (branch == NULL) ? | 542 const bool left_is_smi = (branch == NULL) ? |
| 547 false : (branch->left()->ResultCid() == kSmiCid); | 543 false : (branch->left()->ResultCid() == kSmiCid); |
| 548 const bool right_is_smi = (branch == NULL) ? | 544 const bool right_is_smi = (branch == NULL) ? |
| 549 false : (branch->right()->ResultCid() == kSmiCid); | 545 false : (branch->right()->ResultCid() == kSmiCid); |
| 550 if (!left_is_smi || !right_is_smi) { | 546 if (!left_is_smi || !right_is_smi) { |
| 551 Register temp = locs.temp(0).reg(); | 547 Register temp = locs.temp(0).reg(); |
| 552 Label* deopt = compiler->AddDeoptStub(deopt_id, | 548 Label* deopt = compiler->AddDeoptStub(deopt_id, kDeoptSmiCompareSmi); |
| 553 try_index, | |
| 554 kDeoptSmiCompareSmi); | |
| 555 __ movl(temp, left); | 549 __ movl(temp, left); |
| 556 __ orl(temp, right); | 550 __ orl(temp, right); |
| 557 __ testl(temp, Immediate(kSmiTagMask)); | 551 __ testl(temp, Immediate(kSmiTagMask)); |
| 558 __ j(NOT_ZERO, deopt); | 552 __ j(NOT_ZERO, deopt); |
| 559 } | 553 } |
| 560 | 554 |
| 561 Condition true_condition = TokenKindToSmiCondition(kind); | 555 Condition true_condition = TokenKindToSmiCondition(kind); |
| 562 __ cmpl(left, right); | 556 __ cmpl(left, right); |
| 563 | 557 |
| 564 if (branch != NULL) { | 558 if (branch != NULL) { |
| (...skipping 23 matching lines...) Expand all Loading... |
| 588 UNREACHABLE(); | 582 UNREACHABLE(); |
| 589 return OVERFLOW; | 583 return OVERFLOW; |
| 590 } | 584 } |
| 591 } | 585 } |
| 592 | 586 |
| 593 | 587 |
| 594 static void EmitDoubleComparisonOp(FlowGraphCompiler* compiler, | 588 static void EmitDoubleComparisonOp(FlowGraphCompiler* compiler, |
| 595 const LocationSummary& locs, | 589 const LocationSummary& locs, |
| 596 Token::Kind kind, | 590 Token::Kind kind, |
| 597 BranchInstr* branch, | 591 BranchInstr* branch, |
| 598 intptr_t deopt_id, | 592 intptr_t deopt_id) { |
| 599 intptr_t try_index) { | |
| 600 Register left = locs.in(0).reg(); | 593 Register left = locs.in(0).reg(); |
| 601 Register right = locs.in(1).reg(); | 594 Register right = locs.in(1).reg(); |
| 602 // TODO(srdjan): temp is only needed if a conversion Smi->Double occurs. | 595 // TODO(srdjan): temp is only needed if a conversion Smi->Double occurs. |
| 603 Register temp = locs.temp(0).reg(); | 596 Register temp = locs.temp(0).reg(); |
| 604 Label* deopt = compiler->AddDeoptStub(deopt_id, | 597 Label* deopt = compiler->AddDeoptStub(deopt_id, kDeoptDoubleComparison); |
| 605 try_index, | |
| 606 kDeoptDoubleComparison); | |
| 607 compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt); | 598 compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt); |
| 608 compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt); | 599 compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt); |
| 609 | 600 |
| 610 Condition true_condition = TokenKindToDoubleCondition(kind); | 601 Condition true_condition = TokenKindToDoubleCondition(kind); |
| 611 if (branch != NULL) { | 602 if (branch != NULL) { |
| 612 compiler->EmitDoubleCompareBranch( | 603 compiler->EmitDoubleCompareBranch( |
| 613 true_condition, XMM0, XMM1, branch); | 604 true_condition, XMM0, XMM1, branch); |
| 614 } else { | 605 } else { |
| 615 compiler->EmitDoubleCompareBool( | 606 compiler->EmitDoubleCompareBool( |
| 616 true_condition, XMM0, XMM1, locs.out().reg()); | 607 true_condition, XMM0, XMM1, locs.out().reg()); |
| 617 } | 608 } |
| 618 } | 609 } |
| 619 | 610 |
| 620 | 611 |
| 621 void EqualityCompareComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 612 void EqualityCompareComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 613 BranchInstr* kNoBranch = NULL; |
| 622 if (receiver_class_id() == kSmiCid) { | 614 if (receiver_class_id() == kSmiCid) { |
| 623 // Deoptimizes if both arguments not Smi. | 615 // Deoptimizes if both arguments not Smi. |
| 624 EmitSmiComparisonOp(compiler, *locs(), kind(), NULL, // No branch. | 616 EmitSmiComparisonOp(compiler, *locs(), kind(), kNoBranch, deopt_id()); |
| 625 deopt_id(), try_index()); | |
| 626 return; | 617 return; |
| 627 } | 618 } |
| 628 if (receiver_class_id() == kDoubleCid) { | 619 if (receiver_class_id() == kDoubleCid) { |
| 629 // Deoptimizes if both arguments are Smi, or if none is Double or Smi. | 620 // Deoptimizes if both arguments are Smi, or if none is Double or Smi. |
| 630 EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL, // No branch. | 621 EmitDoubleComparisonOp(compiler, *locs(), kind(), kNoBranch, deopt_id()); |
| 631 deopt_id(), try_index()); | |
| 632 return; | 622 return; |
| 633 } | 623 } |
| 634 const bool is_checked_strict_equal = | 624 const bool is_checked_strict_equal = |
| 635 HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid); | 625 HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid); |
| 636 if (is_checked_strict_equal) { | 626 if (is_checked_strict_equal) { |
| 637 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), NULL, | 627 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), kNoBranch, |
| 638 deopt_id(), try_index()); | 628 deopt_id()); |
| 639 return; | 629 return; |
| 640 } | 630 } |
| 641 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { | 631 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { |
| 642 EmitGenericEqualityCompare(compiler, locs(), kind(), NULL, *ic_data(), | 632 EmitGenericEqualityCompare(compiler, locs(), kind(), kNoBranch, *ic_data(), |
| 643 deopt_id(), token_pos(), try_index()); | 633 deopt_id(), token_pos(), try_index()); |
| 644 } else { | 634 } else { |
| 645 Register left = locs()->in(0).reg(); | 635 Register left = locs()->in(0).reg(); |
| 646 Register right = locs()->in(1).reg(); | 636 Register right = locs()->in(1).reg(); |
| 647 __ pushl(left); | 637 __ pushl(left); |
| 648 __ pushl(right); | 638 __ pushl(right); |
| 649 EmitEqualityAsInstanceCall(compiler, | 639 EmitEqualityAsInstanceCall(compiler, |
| 650 deopt_id(), | 640 deopt_id(), |
| 651 token_pos(), | 641 token_pos(), |
| 652 try_index(), | 642 try_index(), |
| (...skipping 22 matching lines...) Expand all Loading... |
| 675 // Pick arbitrary fixed input registers because this is a call. | 665 // Pick arbitrary fixed input registers because this is a call. |
| 676 locs->set_in(0, Location::RegisterLocation(EAX)); | 666 locs->set_in(0, Location::RegisterLocation(EAX)); |
| 677 locs->set_in(1, Location::RegisterLocation(ECX)); | 667 locs->set_in(1, Location::RegisterLocation(ECX)); |
| 678 locs->set_out(Location::RegisterLocation(EAX)); | 668 locs->set_out(Location::RegisterLocation(EAX)); |
| 679 return locs; | 669 return locs; |
| 680 } | 670 } |
| 681 | 671 |
| 682 | 672 |
| 683 void RelationalOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 673 void RelationalOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 684 if (operands_class_id() == kSmiCid) { | 674 if (operands_class_id() == kSmiCid) { |
| 685 EmitSmiComparisonOp(compiler, *locs(), kind(), NULL, | 675 EmitSmiComparisonOp(compiler, *locs(), kind(), NULL, deopt_id()); |
| 686 deopt_id(), try_index()); | |
| 687 return; | 676 return; |
| 688 } | 677 } |
| 689 if (operands_class_id() == kDoubleCid) { | 678 if (operands_class_id() == kDoubleCid) { |
| 690 EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL, | 679 EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL, deopt_id()); |
| 691 deopt_id(), try_index()); | |
| 692 return; | 680 return; |
| 693 } | 681 } |
| 694 | 682 |
| 695 // Push arguments for the call. | 683 // Push arguments for the call. |
| 696 // TODO(fschneider): Split this instruction into different types to avoid | 684 // TODO(fschneider): Split this instruction into different types to avoid |
| 697 // explicitly pushing arguments to the call here. | 685 // explicitly pushing arguments to the call here. |
| 698 Register left = locs()->in(0).reg(); | 686 Register left = locs()->in(0).reg(); |
| 699 Register right = locs()->in(1).reg(); | 687 Register right = locs()->in(1).reg(); |
| 700 __ pushl(left); | 688 __ pushl(left); |
| 701 __ pushl(right); | 689 __ pushl(right); |
| 702 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { | 690 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { |
| 703 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 691 Label* deopt = compiler->AddDeoptStub(deopt_id(), kDeoptRelationalOp); |
| 704 try_index(), | |
| 705 kDeoptRelationalOp); | |
| 706 // Load class into EDI. Since this is a call, any register except | 692 // Load class into EDI. Since this is a call, any register except |
| 707 // the fixed input registers would be ok. | 693 // the fixed input registers would be ok. |
| 708 ASSERT((left != EDI) && (right != EDI)); | 694 ASSERT((left != EDI) && (right != EDI)); |
| 709 Label done; | 695 Label done; |
| 710 const intptr_t kNumArguments = 2; | 696 const intptr_t kNumArguments = 2; |
| 711 __ movl(EDI, Immediate(kSmiCid)); | 697 __ movl(EDI, Immediate(kSmiCid)); |
| 712 __ testl(left, Immediate(kSmiTagMask)); | 698 __ testl(left, Immediate(kSmiTagMask)); |
| 713 __ j(ZERO, &done); | 699 __ j(ZERO, &done); |
| 714 __ LoadClassId(EDI, left); | 700 __ LoadClassId(EDI, left); |
| 715 __ Bind(&done); | 701 __ Bind(&done); |
| (...skipping 363 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1079 LocationSummary::kNoCall); | 1065 LocationSummary::kNoCall); |
| 1080 } | 1066 } |
| 1081 | 1067 |
| 1082 | 1068 |
| 1083 void LoadVMFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1069 void LoadVMFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1084 Register instance_reg = locs()->in(0).reg(); | 1070 Register instance_reg = locs()->in(0).reg(); |
| 1085 Register result_reg = locs()->out().reg(); | 1071 Register result_reg = locs()->out().reg(); |
| 1086 if (HasICData()) { | 1072 if (HasICData()) { |
| 1087 ASSERT(original() != NULL); | 1073 ASSERT(original() != NULL); |
| 1088 Label* deopt = compiler->AddDeoptStub(original()->deopt_id(), | 1074 Label* deopt = compiler->AddDeoptStub(original()->deopt_id(), |
| 1089 original()->try_index(), | |
| 1090 kDeoptInstanceGetterSameTarget); | 1075 kDeoptInstanceGetterSameTarget); |
| 1091 // Smis do not have instance fields (Smi class is always first). | 1076 // Smis do not have instance fields (Smi class is always first). |
| 1092 // Use 'result' as temporary register. | 1077 // Use 'result' as temporary register. |
| 1093 ASSERT(result_reg != instance_reg); | 1078 ASSERT(result_reg != instance_reg); |
| 1094 ASSERT(ic_data() != NULL); | 1079 ASSERT(ic_data() != NULL); |
| 1095 compiler->EmitClassChecksNoSmi(*ic_data(), instance_reg, result_reg, deopt); | 1080 compiler->EmitClassChecksNoSmi(*ic_data(), instance_reg, result_reg, deopt); |
| 1096 } | 1081 } |
| 1097 | 1082 |
| 1098 __ movl(result_reg, FieldAddress(instance_reg, offset_in_bytes())); | 1083 __ movl(result_reg, FieldAddress(instance_reg, offset_in_bytes())); |
| 1099 } | 1084 } |
| (...skipping 364 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1464 ASSERT(left == result); | 1449 ASSERT(left == result); |
| 1465 Label* deopt = NULL; | 1450 Label* deopt = NULL; |
| 1466 switch (op_kind()) { | 1451 switch (op_kind()) { |
| 1467 case Token::kBIT_AND: | 1452 case Token::kBIT_AND: |
| 1468 case Token::kBIT_OR: | 1453 case Token::kBIT_OR: |
| 1469 case Token::kBIT_XOR: | 1454 case Token::kBIT_XOR: |
| 1470 // Can't deoptimize. Arguments are already checked for smi. | 1455 // Can't deoptimize. Arguments are already checked for smi. |
| 1471 break; | 1456 break; |
| 1472 default: | 1457 default: |
| 1473 deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), | 1458 deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), |
| 1474 instance_call()->try_index(), | |
| 1475 kDeoptBinarySmiOp); | 1459 kDeoptBinarySmiOp); |
| 1476 } | 1460 } |
| 1477 | 1461 |
| 1478 switch (op_kind()) { | 1462 switch (op_kind()) { |
| 1479 case Token::kADD: { | 1463 case Token::kADD: { |
| 1480 __ addl(left, right); | 1464 __ addl(left, right); |
| 1481 __ j(OVERFLOW, deopt); | 1465 __ j(OVERFLOW, deopt); |
| 1482 break; | 1466 break; |
| 1483 } | 1467 } |
| 1484 case Token::kSUB: { | 1468 case Token::kSUB: { |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1633 // receiver and a Mint or Smi argument. We fall back to the run time call if | 1617 // receiver and a Mint or Smi argument. We fall back to the run time call if |
| 1634 // both receiver and argument are Mint or if one of them is Mint and the other | 1618 // both receiver and argument are Mint or if one of them is Mint and the other |
| 1635 // is a negative Smi. | 1619 // is a negative Smi. |
| 1636 Register left = locs()->in(0).reg(); | 1620 Register left = locs()->in(0).reg(); |
| 1637 Register right = locs()->in(1).reg(); | 1621 Register right = locs()->in(1).reg(); |
| 1638 Register result = locs()->out().reg(); | 1622 Register result = locs()->out().reg(); |
| 1639 Register temp = locs()->temp(0).reg(); | 1623 Register temp = locs()->temp(0).reg(); |
| 1640 ASSERT(left == result); | 1624 ASSERT(left == result); |
| 1641 ASSERT(op_kind() == Token::kBIT_AND); | 1625 ASSERT(op_kind() == Token::kBIT_AND); |
| 1642 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), | 1626 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), |
| 1643 instance_call()->try_index(), | |
| 1644 kDeoptBinaryMintOp); | 1627 kDeoptBinaryMintOp); |
| 1645 Label mint_static_call, smi_static_call, non_smi, smi_smi, done; | 1628 Label mint_static_call, smi_static_call, non_smi, smi_smi, done; |
| 1646 __ testl(left, Immediate(kSmiTagMask)); // Is receiver Smi? | 1629 __ testl(left, Immediate(kSmiTagMask)); // Is receiver Smi? |
| 1647 __ j(NOT_ZERO, &non_smi); | 1630 __ j(NOT_ZERO, &non_smi); |
| 1648 __ testl(right, Immediate(kSmiTagMask)); // Is argument Smi? | 1631 __ testl(right, Immediate(kSmiTagMask)); // Is argument Smi? |
| 1649 __ j(ZERO, &smi_smi); | 1632 __ j(ZERO, &smi_smi); |
| 1650 __ CompareClassId(right, kMintCid, temp); // Is argument Mint? | 1633 __ CompareClassId(right, kMintCid, temp); // Is argument Mint? |
| 1651 __ j(NOT_EQUAL, deopt); // Argument neither Smi nor Mint. | 1634 __ j(NOT_EQUAL, deopt); // Argument neither Smi nor Mint. |
| 1652 __ cmpl(left, Immediate(0)); | 1635 __ cmpl(left, Immediate(0)); |
| 1653 __ j(LESS, &smi_static_call); // Negative Smi receiver, Mint argument. | 1636 __ j(LESS, &smi_static_call); // Negative Smi receiver, Mint argument. |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1740 instance_call()->try_index(), | 1723 instance_call()->try_index(), |
| 1741 &label, | 1724 &label, |
| 1742 PcDescriptors::kOther, | 1725 PcDescriptors::kOther, |
| 1743 locs()); | 1726 locs()); |
| 1744 // Newly allocated object is now in the result register (RAX). | 1727 // Newly allocated object is now in the result register (RAX). |
| 1745 ASSERT(result == EAX); | 1728 ASSERT(result == EAX); |
| 1746 __ movl(right, Address(ESP, 0)); | 1729 __ movl(right, Address(ESP, 0)); |
| 1747 __ movl(left, Address(ESP, kWordSize)); | 1730 __ movl(left, Address(ESP, kWordSize)); |
| 1748 | 1731 |
| 1749 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), | 1732 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), |
| 1750 instance_call()->try_index(), | |
| 1751 kDeoptBinaryDoubleOp); | 1733 kDeoptBinaryDoubleOp); |
| 1752 | 1734 |
| 1753 // Binary operation of two Smi's produces a Smi not a double. | 1735 // Binary operation of two Smi's produces a Smi not a double. |
| 1754 __ movl(temp, left); | 1736 __ movl(temp, left); |
| 1755 __ orl(temp, right); | 1737 __ orl(temp, right); |
| 1756 __ testl(temp, Immediate(kSmiTagMask)); | 1738 __ testl(temp, Immediate(kSmiTagMask)); |
| 1757 __ j(ZERO, deopt); | 1739 __ j(ZERO, deopt); |
| 1758 | 1740 |
| 1759 compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt); | 1741 compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt); |
| 1760 compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt); | 1742 compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 1782 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1764 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1783 summary->set_in(0, Location::RequiresRegister()); | 1765 summary->set_in(0, Location::RequiresRegister()); |
| 1784 summary->set_in(1, Location::RequiresRegister()); | 1766 summary->set_in(1, Location::RequiresRegister()); |
| 1785 summary->set_temp(0, Location::RequiresRegister()); | 1767 summary->set_temp(0, Location::RequiresRegister()); |
| 1786 return summary; | 1768 return summary; |
| 1787 } | 1769 } |
| 1788 | 1770 |
| 1789 | 1771 |
| 1790 void CheckEitherNonSmiComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1772 void CheckEitherNonSmiComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1791 Label* deopt = compiler->AddDeoptStub(instance_call_->deopt_id(), | 1773 Label* deopt = compiler->AddDeoptStub(instance_call_->deopt_id(), |
| 1792 instance_call_->try_index(), | |
| 1793 kDeoptBinaryDoubleOp); | 1774 kDeoptBinaryDoubleOp); |
| 1794 | 1775 |
| 1795 Register temp = locs()->temp(0).reg(); | 1776 Register temp = locs()->temp(0).reg(); |
| 1796 __ movl(temp, locs()->in(0).reg()); | 1777 __ movl(temp, locs()->in(0).reg()); |
| 1797 __ orl(temp, locs()->in(1).reg()); | 1778 __ orl(temp, locs()->in(1).reg()); |
| 1798 __ testl(temp, Immediate(kSmiTagMask)); | 1779 __ testl(temp, Immediate(kSmiTagMask)); |
| 1799 __ j(ZERO, deopt); | 1780 __ j(ZERO, deopt); |
| 1800 } | 1781 } |
| 1801 | 1782 |
| 1802 | 1783 |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1878 } | 1859 } |
| 1879 | 1860 |
| 1880 | 1861 |
| 1881 void UnboxDoubleComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1862 void UnboxDoubleComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1882 const intptr_t v_cid = value()->ResultCid(); | 1863 const intptr_t v_cid = value()->ResultCid(); |
| 1883 | 1864 |
| 1884 const Register value = locs()->in(0).reg(); | 1865 const Register value = locs()->in(0).reg(); |
| 1885 const XmmRegister result = locs()->out().xmm_reg(); | 1866 const XmmRegister result = locs()->out().xmm_reg(); |
| 1886 if (v_cid != kDoubleCid) { | 1867 if (v_cid != kDoubleCid) { |
| 1887 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), | 1868 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), |
| 1888 instance_call()->try_index(), | |
| 1889 kDeoptBinaryDoubleOp); | 1869 kDeoptBinaryDoubleOp); |
| 1890 compiler->LoadDoubleOrSmiToXmm(result, | 1870 compiler->LoadDoubleOrSmiToXmm(result, |
| 1891 value, | 1871 value, |
| 1892 locs()->temp(0).reg(), | 1872 locs()->temp(0).reg(), |
| 1893 deopt); | 1873 deopt); |
| 1894 } else { | 1874 } else { |
| 1895 __ movsd(result, FieldAddress(value, Double::value_offset())); | 1875 __ movsd(result, FieldAddress(value, Double::value_offset())); |
| 1896 } | 1876 } |
| 1897 } | 1877 } |
| 1898 | 1878 |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1935 return summary; | 1915 return summary; |
| 1936 } | 1916 } |
| 1937 | 1917 |
| 1938 | 1918 |
| 1939 void UnarySmiOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1919 void UnarySmiOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1940 Register value = locs()->in(0).reg(); | 1920 Register value = locs()->in(0).reg(); |
| 1941 ASSERT(value == locs()->out().reg()); | 1921 ASSERT(value == locs()->out().reg()); |
| 1942 switch (op_kind()) { | 1922 switch (op_kind()) { |
| 1943 case Token::kNEGATE: { | 1923 case Token::kNEGATE: { |
| 1944 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), | 1924 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), |
| 1945 instance_call()->try_index(), | |
| 1946 kDeoptUnaryOp); | 1925 kDeoptUnaryOp); |
| 1947 __ negl(value); | 1926 __ negl(value); |
| 1948 __ j(OVERFLOW, deopt); | 1927 __ j(OVERFLOW, deopt); |
| 1949 break; | 1928 break; |
| 1950 } | 1929 } |
| 1951 case Token::kBIT_NOT: | 1930 case Token::kBIT_NOT: |
| 1952 __ notl(value); | 1931 __ notl(value); |
| 1953 __ andl(value, Immediate(~kSmiTagMask)); // Remove inverted smi-tag. | 1932 __ andl(value, Immediate(~kSmiTagMask)); // Remove inverted smi-tag. |
| 1954 break; | 1933 break; |
| 1955 default: | 1934 default: |
| (...skipping 22 matching lines...) Expand all Loading... |
| 1978 // TODO(srdjan): Implement for more checks. | 1957 // TODO(srdjan): Implement for more checks. |
| 1979 ASSERT(ic_data.NumberOfChecks() == 1); | 1958 ASSERT(ic_data.NumberOfChecks() == 1); |
| 1980 intptr_t test_class_id; | 1959 intptr_t test_class_id; |
| 1981 Function& target = Function::Handle(); | 1960 Function& target = Function::Handle(); |
| 1982 ic_data.GetOneClassCheckAt(0, &test_class_id, &target); | 1961 ic_data.GetOneClassCheckAt(0, &test_class_id, &target); |
| 1983 | 1962 |
| 1984 Register value = locs()->in(0).reg(); | 1963 Register value = locs()->in(0).reg(); |
| 1985 Register result = locs()->out().reg(); | 1964 Register result = locs()->out().reg(); |
| 1986 ASSERT(value == result); | 1965 ASSERT(value == result); |
| 1987 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), | 1966 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), |
| 1988 instance_call()->try_index(), | |
| 1989 kDeoptUnaryOp); | 1967 kDeoptUnaryOp); |
| 1990 if (test_class_id == kDoubleCid) { | 1968 if (test_class_id == kDoubleCid) { |
| 1991 Register temp = locs()->temp(0).reg(); | 1969 Register temp = locs()->temp(0).reg(); |
| 1992 __ testl(value, Immediate(kSmiTagMask)); | 1970 __ testl(value, Immediate(kSmiTagMask)); |
| 1993 __ j(ZERO, deopt); // Smi. | 1971 __ j(ZERO, deopt); // Smi. |
| 1994 __ CompareClassId(value, kDoubleCid, temp); | 1972 __ CompareClassId(value, kDoubleCid, temp); |
| 1995 __ j(NOT_EQUAL, deopt); | 1973 __ j(NOT_EQUAL, deopt); |
| 1996 // Allocate result object. | 1974 // Allocate result object. |
| 1997 const Class& double_class = compiler->double_class(); | 1975 const Class& double_class = compiler->double_class(); |
| 1998 const Code& stub = | 1976 const Code& stub = |
| (...skipping 29 matching lines...) Expand all Loading... |
| 2028 locs->set_out(Location::SameAsFirstInput()); | 2006 locs->set_out(Location::SameAsFirstInput()); |
| 2029 return locs; | 2007 return locs; |
| 2030 } | 2008 } |
| 2031 | 2009 |
| 2032 | 2010 |
| 2033 void DoubleToDoubleComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 2011 void DoubleToDoubleComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2034 Register value = locs()->in(0).reg(); | 2012 Register value = locs()->in(0).reg(); |
| 2035 Register result = locs()->out().reg(); | 2013 Register result = locs()->out().reg(); |
| 2036 | 2014 |
| 2037 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), | 2015 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), |
| 2038 instance_call()->try_index(), | |
| 2039 kDeoptDoubleToDouble); | 2016 kDeoptDoubleToDouble); |
| 2040 Register temp = locs()->temp(0).reg(); | 2017 Register temp = locs()->temp(0).reg(); |
| 2041 __ testl(value, Immediate(kSmiTagMask)); | 2018 __ testl(value, Immediate(kSmiTagMask)); |
| 2042 __ j(ZERO, deopt); // Deoptimize if Smi. | 2019 __ j(ZERO, deopt); // Deoptimize if Smi. |
| 2043 __ CompareClassId(value, kDoubleCid, temp); | 2020 __ CompareClassId(value, kDoubleCid, temp); |
| 2044 __ j(NOT_EQUAL, deopt); // Deoptimize if not Double. | 2021 __ j(NOT_EQUAL, deopt); // Deoptimize if not Double. |
| 2045 ASSERT(value == result); | 2022 ASSERT(value == result); |
| 2046 } | 2023 } |
| 2047 | 2024 |
| 2048 | 2025 |
| 2049 LocationSummary* SmiToDoubleComp::MakeLocationSummary() const { | 2026 LocationSummary* SmiToDoubleComp::MakeLocationSummary() const { |
| 2050 return MakeCallSummary(); // Calls a stub to allocate result. | 2027 return MakeCallSummary(); // Calls a stub to allocate result. |
| 2051 } | 2028 } |
| 2052 | 2029 |
| 2053 | 2030 |
| 2054 void SmiToDoubleComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 2031 void SmiToDoubleComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2055 Register result = locs()->out().reg(); | 2032 Register result = locs()->out().reg(); |
| 2056 | 2033 |
| 2057 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), | 2034 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), |
| 2058 instance_call()->try_index(), | |
| 2059 kDeoptIntegerToDouble); | 2035 kDeoptIntegerToDouble); |
| 2060 | 2036 |
| 2061 const Class& double_class = compiler->double_class(); | 2037 const Class& double_class = compiler->double_class(); |
| 2062 const Code& stub = | 2038 const Code& stub = |
| 2063 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); | 2039 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); |
| 2064 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); | 2040 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); |
| 2065 | 2041 |
| 2066 // TODO(vegorov): allocate box in the driver loop to avoid spilling. | 2042 // TODO(vegorov): allocate box in the driver loop to avoid spilling. |
| 2067 compiler->GenerateCall(instance_call()->token_pos(), | 2043 compiler->GenerateCall(instance_call()->token_pos(), |
| 2068 instance_call()->try_index(), | 2044 instance_call()->try_index(), |
| (...skipping 14 matching lines...) Expand all Loading... |
| 2083 } | 2059 } |
| 2084 | 2060 |
| 2085 | 2061 |
| 2086 LocationSummary* PolymorphicInstanceCallComp::MakeLocationSummary() const { | 2062 LocationSummary* PolymorphicInstanceCallComp::MakeLocationSummary() const { |
| 2087 return MakeCallSummary(); | 2063 return MakeCallSummary(); |
| 2088 } | 2064 } |
| 2089 | 2065 |
| 2090 | 2066 |
| 2091 void PolymorphicInstanceCallComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 2067 void PolymorphicInstanceCallComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2092 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), | 2068 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), |
| 2093 instance_call()->try_index(), | |
| 2094 kDeoptPolymorphicInstanceCallTestFail); | 2069 kDeoptPolymorphicInstanceCallTestFail); |
| 2095 if (!HasICData() || (ic_data()->NumberOfChecks() == 0)) { | 2070 if (!HasICData() || (ic_data()->NumberOfChecks() == 0)) { |
| 2096 __ jmp(deopt); | 2071 __ jmp(deopt); |
| 2097 return; | 2072 return; |
| 2098 } | 2073 } |
| 2099 ASSERT(HasICData()); | 2074 ASSERT(HasICData()); |
| 2100 ASSERT(ic_data()->num_args_tested() == 1); | 2075 ASSERT(ic_data()->num_args_tested() == 1); |
| 2101 if (!with_checks()) { | 2076 if (!with_checks()) { |
| 2102 const Function& target = Function::ZoneHandle(ic_data()->GetTargetAt(0)); | 2077 const Function& target = Function::ZoneHandle(ic_data()->GetTargetAt(0)); |
| 2103 compiler->GenerateStaticCall(instance_call()->deopt_id(), | 2078 compiler->GenerateStaticCall(instance_call()->deopt_id(), |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2186 locs->set_in(0, Location::RegisterLocation(EAX)); | 2161 locs->set_in(0, Location::RegisterLocation(EAX)); |
| 2187 locs->set_in(1, Location::RegisterLocation(ECX)); | 2162 locs->set_in(1, Location::RegisterLocation(ECX)); |
| 2188 return locs; | 2163 return locs; |
| 2189 } | 2164 } |
| 2190 | 2165 |
| 2191 | 2166 |
| 2192 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2167 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2193 // Relational or equality. | 2168 // Relational or equality. |
| 2194 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { | 2169 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { |
| 2195 if (ICDataWithBothClassIds(*ic_data(), kSmiCid)) { | 2170 if (ICDataWithBothClassIds(*ic_data(), kSmiCid)) { |
| 2196 EmitSmiComparisonOp(compiler, *locs(), kind(), this, | 2171 EmitSmiComparisonOp(compiler, *locs(), kind(), this, deopt_id()); |
| 2197 deopt_id(), try_index()); | |
| 2198 return; | 2172 return; |
| 2199 } | 2173 } |
| 2200 if (ICDataWithBothClassIds(*ic_data(), kDoubleCid)) { | 2174 if (ICDataWithBothClassIds(*ic_data(), kDoubleCid)) { |
| 2201 EmitDoubleComparisonOp(compiler, *locs(), kind(), this, | 2175 EmitDoubleComparisonOp(compiler, *locs(), kind(), this, deopt_id()); |
| 2202 deopt_id(), try_index()); | |
| 2203 return; | 2176 return; |
| 2204 } | 2177 } |
| 2205 if (IsCheckedStrictEquals(*ic_data(), kind())) { | 2178 if (IsCheckedStrictEquals(*ic_data(), kind())) { |
| 2206 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), this, | 2179 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), this, |
| 2207 deopt_id(), try_index()); | 2180 deopt_id()); |
| 2208 return; | 2181 return; |
| 2209 } | 2182 } |
| 2210 | 2183 |
| 2211 // TODO(srdjan): Add Smi/Double, Double/Smi comparisons. | 2184 // TODO(srdjan): Add Smi/Double, Double/Smi comparisons. |
| 2212 if ((kind() == Token::kEQ) || (kind() == Token::kNE)) { | 2185 if ((kind() == Token::kEQ) || (kind() == Token::kNE)) { |
| 2213 EmitGenericEqualityCompare(compiler, locs(), kind(), this, *ic_data(), | 2186 EmitGenericEqualityCompare(compiler, locs(), kind(), this, *ic_data(), |
| 2214 deopt_id(), token_pos(), try_index()); | 2187 deopt_id(), token_pos(), try_index()); |
| 2215 return; | 2188 return; |
| 2216 } | 2189 } |
| 2217 // Otherwise polymorphic dispatch? | 2190 // Otherwise polymorphic dispatch? |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2279 summary->set_in(0, Location::RequiresRegister()); | 2252 summary->set_in(0, Location::RequiresRegister()); |
| 2280 summary->set_temp(0, Location::RequiresRegister()); | 2253 summary->set_temp(0, Location::RequiresRegister()); |
| 2281 return summary; | 2254 return summary; |
| 2282 } | 2255 } |
| 2283 | 2256 |
| 2284 | 2257 |
| 2285 void CheckClassComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 2258 void CheckClassComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2286 Register value = locs()->in(0).reg(); | 2259 Register value = locs()->in(0).reg(); |
| 2287 Register temp = locs()->temp(0).reg(); | 2260 Register temp = locs()->temp(0).reg(); |
| 2288 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 2261 Label* deopt = compiler->AddDeoptStub(deopt_id(), |
| 2289 try_index(), | |
| 2290 kDeoptCheckClass); | 2262 kDeoptCheckClass); |
| 2291 ASSERT(ic_data()->GetReceiverClassIdAt(0) != kSmiCid); | 2263 ASSERT(ic_data()->GetReceiverClassIdAt(0) != kSmiCid); |
| 2292 __ testl(value, Immediate(kSmiTagMask)); | 2264 __ testl(value, Immediate(kSmiTagMask)); |
| 2293 __ j(ZERO, deopt); | 2265 __ j(ZERO, deopt); |
| 2294 __ LoadClassId(temp, value); | 2266 __ LoadClassId(temp, value); |
| 2295 Label is_ok; | 2267 Label is_ok; |
| 2296 const intptr_t num_checks = ic_data()->NumberOfChecks(); | 2268 const intptr_t num_checks = ic_data()->NumberOfChecks(); |
| 2297 const bool use_near_jump = num_checks < 5; | 2269 const bool use_near_jump = num_checks < 5; |
| 2298 for (intptr_t i = 0; i < num_checks; i++) { | 2270 for (intptr_t i = 0; i < num_checks; i++) { |
| 2299 __ cmpl(temp, Immediate(ic_data()->GetReceiverClassIdAt(i))); | 2271 __ cmpl(temp, Immediate(ic_data()->GetReceiverClassIdAt(i))); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 2317 LocationSummary* summary = | 2289 LocationSummary* summary = |
| 2318 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2290 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 2319 summary->set_in(0, Location::RequiresRegister()); | 2291 summary->set_in(0, Location::RequiresRegister()); |
| 2320 return summary; | 2292 return summary; |
| 2321 } | 2293 } |
| 2322 | 2294 |
| 2323 | 2295 |
| 2324 void CheckSmiComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 2296 void CheckSmiComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2325 Register value = locs()->in(0).reg(); | 2297 Register value = locs()->in(0).reg(); |
| 2326 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 2298 Label* deopt = compiler->AddDeoptStub(deopt_id(), |
| 2327 try_index(), | |
| 2328 kDeoptCheckSmi); | 2299 kDeoptCheckSmi); |
| 2329 __ testl(value, Immediate(kSmiTagMask)); | 2300 __ testl(value, Immediate(kSmiTagMask)); |
| 2330 __ j(NOT_ZERO, deopt); | 2301 __ j(NOT_ZERO, deopt); |
| 2331 } | 2302 } |
| 2332 | 2303 |
| 2333 | 2304 |
| 2334 LocationSummary* CheckArrayBoundComp::MakeLocationSummary() const { | 2305 LocationSummary* CheckArrayBoundComp::MakeLocationSummary() const { |
| 2335 return LocationSummary::Make(2, | 2306 return LocationSummary::Make(2, |
| 2336 Location::NoLocation(), | 2307 Location::NoLocation(), |
| 2337 LocationSummary::kNoCall); | 2308 LocationSummary::kNoCall); |
| 2338 } | 2309 } |
| 2339 | 2310 |
| 2340 | 2311 |
| 2341 void CheckArrayBoundComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 2312 void CheckArrayBoundComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2342 Register receiver = locs()->in(0).reg(); | 2313 Register receiver = locs()->in(0).reg(); |
| 2343 Register index = locs()->in(1).reg(); | 2314 Register index = locs()->in(1).reg(); |
| 2344 | 2315 |
| 2345 const DeoptReasonId deopt_reason = | 2316 const DeoptReasonId deopt_reason = |
| 2346 (array_type() == kGrowableObjectArrayCid) ? | 2317 (array_type() == kGrowableObjectArrayCid) ? |
| 2347 kDeoptLoadIndexedGrowableArray : kDeoptLoadIndexedFixedArray; | 2318 kDeoptLoadIndexedGrowableArray : kDeoptLoadIndexedFixedArray; |
| 2348 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 2319 Label* deopt = compiler->AddDeoptStub(deopt_id(), |
| 2349 try_index(), | |
| 2350 deopt_reason); | 2320 deopt_reason); |
| 2351 switch (array_type()) { | 2321 switch (array_type()) { |
| 2352 case kArrayCid: | 2322 case kArrayCid: |
| 2353 case kImmutableArrayCid: | 2323 case kImmutableArrayCid: |
| 2354 __ cmpl(index, FieldAddress(receiver, Array::length_offset())); | 2324 __ cmpl(index, FieldAddress(receiver, Array::length_offset())); |
| 2355 break; | 2325 break; |
| 2356 case kGrowableObjectArrayCid: | 2326 case kGrowableObjectArrayCid: |
| 2357 __ cmpl(index, | 2327 __ cmpl(index, |
| 2358 FieldAddress(receiver, GrowableObjectArray::length_offset())); | 2328 FieldAddress(receiver, GrowableObjectArray::length_offset())); |
| 2359 break; | 2329 break; |
| 2360 } | 2330 } |
| 2361 __ j(ABOVE_EQUAL, deopt); | 2331 __ j(ABOVE_EQUAL, deopt); |
| 2362 } | 2332 } |
| 2363 | 2333 |
| 2364 | 2334 |
| 2365 } // namespace dart | 2335 } // namespace dart |
| 2366 | 2336 |
| 2367 #undef __ | 2337 #undef __ |
| 2368 | 2338 |
| 2369 #endif // defined TARGET_ARCH_X64 | 2339 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |