| 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 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 243 case Token::kGTE: return GREATER_EQUAL; | 243 case Token::kGTE: return GREATER_EQUAL; |
| 244 default: | 244 default: |
| 245 UNREACHABLE(); | 245 UNREACHABLE(); |
| 246 return OVERFLOW; | 246 return OVERFLOW; |
| 247 } | 247 } |
| 248 } | 248 } |
| 249 | 249 |
| 250 | 250 |
| 251 LocationSummary* EqualityCompareComp::MakeLocationSummary() const { | 251 LocationSummary* EqualityCompareComp::MakeLocationSummary() const { |
| 252 const intptr_t kNumInputs = 2; | 252 const intptr_t kNumInputs = 2; |
| 253 if (receiver_class_id() != kObject) { | 253 if (receiver_class_id() != kObjectCid) { |
| 254 ASSERT((receiver_class_id() == kSmi) || (receiver_class_id() == kDouble)); | 254 ASSERT((receiver_class_id() == kSmiCid) || |
| 255 (receiver_class_id() == kDoubleCid)); |
| 255 const intptr_t kNumTemps = 1; | 256 const intptr_t kNumTemps = 1; |
| 256 LocationSummary* locs = | 257 LocationSummary* locs = |
| 257 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 258 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 258 locs->set_in(0, Location::RequiresRegister()); | 259 locs->set_in(0, Location::RequiresRegister()); |
| 259 locs->set_in(1, Location::RequiresRegister()); | 260 locs->set_in(1, Location::RequiresRegister()); |
| 260 locs->set_temp(0, Location::RequiresRegister()); | 261 locs->set_temp(0, Location::RequiresRegister()); |
| 261 locs->set_out(Location::RequiresRegister()); | 262 locs->set_out(Location::RequiresRegister()); |
| 262 return locs; | 263 return locs; |
| 263 } | 264 } |
| 264 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { | 265 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 326 ASSERT(ic_data.NumberOfChecks() > 0); | 327 ASSERT(ic_data.NumberOfChecks() > 0); |
| 327 ASSERT(ic_data.num_args_tested() == 1); | 328 ASSERT(ic_data.num_args_tested() == 1); |
| 328 Label* deopt = compiler->AddDeoptStub(deopt_id, | 329 Label* deopt = compiler->AddDeoptStub(deopt_id, |
| 329 token_pos, | 330 token_pos, |
| 330 try_index, | 331 try_index, |
| 331 kDeoptEquality); | 332 kDeoptEquality); |
| 332 Register left = locs.in(0).reg(); | 333 Register left = locs.in(0).reg(); |
| 333 Register right = locs.in(1).reg(); | 334 Register right = locs.in(1).reg(); |
| 334 __ testq(left, Immediate(kSmiTagMask)); | 335 __ testq(left, Immediate(kSmiTagMask)); |
| 335 Register temp = locs.temp(0).reg(); | 336 Register temp = locs.temp(0).reg(); |
| 336 if (ic_data.GetReceiverClassIdAt(0) == kSmi) { | 337 if (ic_data.GetReceiverClassIdAt(0) == kSmiCid) { |
| 337 Label done, load_class_id; | 338 Label done, load_class_id; |
| 338 __ j(NOT_ZERO, &load_class_id, Assembler::kNearJump); | 339 __ j(NOT_ZERO, &load_class_id, Assembler::kNearJump); |
| 339 __ movq(temp, Immediate(kSmi)); | 340 __ movq(temp, Immediate(kSmiCid)); |
| 340 __ jmp(&done, Assembler::kNearJump); | 341 __ jmp(&done, Assembler::kNearJump); |
| 341 __ Bind(&load_class_id); | 342 __ Bind(&load_class_id); |
| 342 __ LoadClassId(temp, left); | 343 __ LoadClassId(temp, left); |
| 343 __ Bind(&done); | 344 __ Bind(&done); |
| 344 } else { | 345 } else { |
| 345 __ j(ZERO, deopt); // Smi deopts. | 346 __ j(ZERO, deopt); // Smi deopts. |
| 346 __ LoadClassId(temp, left); | 347 __ LoadClassId(temp, left); |
| 347 } | 348 } |
| 348 Condition cond = TokenKindToSmiCondition(kind); | 349 Condition cond = TokenKindToSmiCondition(kind); |
| 349 Label done; | 350 Label done; |
| 350 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { | 351 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { |
| 351 ASSERT((ic_data.GetReceiverClassIdAt(i) != kSmi) || (i == 0)); | 352 ASSERT((ic_data.GetReceiverClassIdAt(i) != kSmiCid) || (i == 0)); |
| 352 Label next_test; | 353 Label next_test; |
| 353 __ cmpq(temp, Immediate(ic_data.GetReceiverClassIdAt(i))); | 354 __ cmpq(temp, Immediate(ic_data.GetReceiverClassIdAt(i))); |
| 354 __ j(NOT_EQUAL, &next_test); | 355 __ j(NOT_EQUAL, &next_test); |
| 355 const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(i)); | 356 const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(i)); |
| 356 ObjectStore* object_store = Isolate::Current()->object_store(); | 357 ObjectStore* object_store = Isolate::Current()->object_store(); |
| 357 if (target.owner() == object_store->object_class()) { | 358 if (target.owner() == object_store->object_class()) { |
| 358 // Object.== is same as ===. | 359 // Object.== is same as ===. |
| 359 __ Drop(2); | 360 __ Drop(2); |
| 360 __ cmpq(left, right); | 361 __ cmpq(left, right); |
| 361 if (branch != NULL) { | 362 if (branch != NULL) { |
| (...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 527 compiler->EmitDoubleCompareBranch( | 528 compiler->EmitDoubleCompareBranch( |
| 528 true_condition, XMM0, XMM1, branch); | 529 true_condition, XMM0, XMM1, branch); |
| 529 } else { | 530 } else { |
| 530 compiler->EmitDoubleCompareBool( | 531 compiler->EmitDoubleCompareBool( |
| 531 true_condition, XMM0, XMM1, locs.out().reg()); | 532 true_condition, XMM0, XMM1, locs.out().reg()); |
| 532 } | 533 } |
| 533 } | 534 } |
| 534 | 535 |
| 535 | 536 |
| 536 void EqualityCompareComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 537 void EqualityCompareComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 537 if (receiver_class_id() == kSmi) { | 538 if (receiver_class_id() == kSmiCid) { |
| 538 EmitSmiComparisonOp(compiler, *locs(), kind(), NULL, // No branch. | 539 EmitSmiComparisonOp(compiler, *locs(), kind(), NULL, // No branch. |
| 539 deopt_id(), token_pos(), try_index()); | 540 deopt_id(), token_pos(), try_index()); |
| 540 return; | 541 return; |
| 541 } | 542 } |
| 542 if (receiver_class_id() == kDouble) { | 543 if (receiver_class_id() == kDoubleCid) { |
| 543 EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL, // No branch. | 544 EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL, // No branch. |
| 544 deopt_id(), token_pos(), try_index()); | 545 deopt_id(), token_pos(), try_index()); |
| 545 return; | 546 return; |
| 546 } | 547 } |
| 547 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { | 548 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { |
| 548 EmitGenericEqualityCompare(compiler, *locs(), kind(), NULL, *ic_data(), | 549 EmitGenericEqualityCompare(compiler, *locs(), kind(), NULL, *ic_data(), |
| 549 deopt_id(), token_pos(), try_index()); | 550 deopt_id(), token_pos(), try_index()); |
| 550 } else { | 551 } else { |
| 551 Register left = locs()->in(0).reg(); | 552 Register left = locs()->in(0).reg(); |
| 552 Register right = locs()->in(1).reg(); | 553 Register right = locs()->in(1).reg(); |
| 553 __ pushq(left); | 554 __ pushq(left); |
| 554 __ pushq(right); | 555 __ pushq(right); |
| 555 EmitEqualityAsInstanceCall(compiler, this); | 556 EmitEqualityAsInstanceCall(compiler, this); |
| 556 } | 557 } |
| 557 } | 558 } |
| 558 | 559 |
| 559 | 560 |
| 560 LocationSummary* RelationalOpComp::MakeLocationSummary() const { | 561 LocationSummary* RelationalOpComp::MakeLocationSummary() const { |
| 561 if (operands_class_id() == kSmi || operands_class_id() == kDouble) { | 562 if (operands_class_id() == kSmiCid || operands_class_id() == kDoubleCid) { |
| 562 const intptr_t kNumInputs = 2; | 563 const intptr_t kNumInputs = 2; |
| 563 const intptr_t kNumTemps = 1; | 564 const intptr_t kNumTemps = 1; |
| 564 LocationSummary* summary = | 565 LocationSummary* summary = |
| 565 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 566 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 566 summary->set_in(0, Location::RequiresRegister()); | 567 summary->set_in(0, Location::RequiresRegister()); |
| 567 summary->set_in(1, Location::RequiresRegister()); | 568 summary->set_in(1, Location::RequiresRegister()); |
| 568 summary->set_out(Location::RequiresRegister()); | 569 summary->set_out(Location::RequiresRegister()); |
| 569 summary->set_temp(0, Location::RequiresRegister()); | 570 summary->set_temp(0, Location::RequiresRegister()); |
| 570 return summary; | 571 return summary; |
| 571 } | 572 } |
| 572 ASSERT(operands_class_id() == kObject); | 573 ASSERT(operands_class_id() == kObjectCid); |
| 573 return MakeCallSummary(); | 574 return MakeCallSummary(); |
| 574 } | 575 } |
| 575 | 576 |
| 576 | 577 |
| 577 void RelationalOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 578 void RelationalOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 578 if (operands_class_id() == kSmi) { | 579 if (operands_class_id() == kSmiCid) { |
| 579 EmitSmiComparisonOp(compiler, *locs(), kind(), NULL, | 580 EmitSmiComparisonOp(compiler, *locs(), kind(), NULL, |
| 580 deopt_id(), token_pos(), try_index()); | 581 deopt_id(), token_pos(), try_index()); |
| 581 return; | 582 return; |
| 582 } | 583 } |
| 583 if (operands_class_id() == kDouble) { | 584 if (operands_class_id() == kDoubleCid) { |
| 584 EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL, | 585 EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL, |
| 585 deopt_id(), token_pos(), try_index()); | 586 deopt_id(), token_pos(), try_index()); |
| 586 return; | 587 return; |
| 587 } | 588 } |
| 588 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { | 589 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { |
| 589 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 590 Label* deopt = compiler->AddDeoptStub(deopt_id(), |
| 590 token_pos(), | 591 token_pos(), |
| 591 try_index(), | 592 try_index(), |
| 592 kDeoptRelationalOp); | 593 kDeoptRelationalOp); |
| 593 // Load receiver into RAX, class into RDI. | 594 // Load receiver into RAX, class into RDI. |
| 594 Label done; | 595 Label done; |
| 595 const intptr_t kNumArguments = 2; | 596 const intptr_t kNumArguments = 2; |
| 596 __ movq(RDI, Immediate(kSmi)); | 597 __ movq(RDI, Immediate(kSmiCid)); |
| 597 __ movq(RAX, Address(RSP, (kNumArguments - 1) * kWordSize)); | 598 __ movq(RAX, Address(RSP, (kNumArguments - 1) * kWordSize)); |
| 598 __ testq(RAX, Immediate(kSmiTagMask)); | 599 __ testq(RAX, Immediate(kSmiTagMask)); |
| 599 __ j(ZERO, &done); | 600 __ j(ZERO, &done); |
| 600 __ LoadClassId(RDI, RAX); | 601 __ LoadClassId(RDI, RAX); |
| 601 __ Bind(&done); | 602 __ Bind(&done); |
| 602 compiler->EmitTestAndCall(ICData::Handle(ic_data()->AsUnaryClassChecks()), | 603 compiler->EmitTestAndCall(ICData::Handle(ic_data()->AsUnaryClassChecks()), |
| 603 RDI, // Class id register. | 604 RDI, // Class id register. |
| 604 kNumArguments, | 605 kNumArguments, |
| 605 Array::Handle(), // No named arguments. | 606 Array::Handle(), // No named arguments. |
| 606 deopt, // Deoptimize target. | 607 deopt, // Deoptimize target. |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 666 compiler->GenerateCall(token_pos(), | 667 compiler->GenerateCall(token_pos(), |
| 667 try_index(), | 668 try_index(), |
| 668 &StubCode::CallNativeCFunctionLabel(), | 669 &StubCode::CallNativeCFunctionLabel(), |
| 669 PcDescriptors::kOther); | 670 PcDescriptors::kOther); |
| 670 __ popq(result); | 671 __ popq(result); |
| 671 } | 672 } |
| 672 | 673 |
| 673 | 674 |
| 674 LocationSummary* LoadIndexedComp::MakeLocationSummary() const { | 675 LocationSummary* LoadIndexedComp::MakeLocationSummary() const { |
| 675 const intptr_t kNumInputs = 2; | 676 const intptr_t kNumInputs = 2; |
| 676 if (receiver_type() == kGrowableObjectArray) { | 677 if (receiver_type() == kGrowableObjectArrayCid) { |
| 677 const intptr_t kNumTemps = 1; | 678 const intptr_t kNumTemps = 1; |
| 678 LocationSummary* locs = | 679 LocationSummary* locs = |
| 679 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 680 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 680 locs->set_in(0, Location::RequiresRegister()); | 681 locs->set_in(0, Location::RequiresRegister()); |
| 681 locs->set_in(1, Location::RequiresRegister()); | 682 locs->set_in(1, Location::RequiresRegister()); |
| 682 locs->set_temp(0, Location::RequiresRegister()); | 683 locs->set_temp(0, Location::RequiresRegister()); |
| 683 locs->set_out(Location::RequiresRegister()); | 684 locs->set_out(Location::RequiresRegister()); |
| 684 return locs; | 685 return locs; |
| 685 } else if ((receiver_type() == kArray) || | 686 } else if ((receiver_type() == kArrayCid) || |
| 686 (receiver_type() == kImmutableArray)) { | 687 (receiver_type() == kImmutableArrayCid)) { |
| 687 return LocationSummary::Make(kNumInputs, | 688 return LocationSummary::Make(kNumInputs, |
| 688 Location::RequiresRegister(), | 689 Location::RequiresRegister(), |
| 689 LocationSummary::kNoCall); | 690 LocationSummary::kNoCall); |
| 690 } else { | 691 } else { |
| 691 ASSERT(receiver_type() == kIllegalObjectKind); | 692 ASSERT(receiver_type() == kIllegalCid); |
| 692 return MakeCallSummary(); | 693 return MakeCallSummary(); |
| 693 } | 694 } |
| 694 } | 695 } |
| 695 | 696 |
| 696 | 697 |
| 697 static void EmitLoadIndexedPolymorphic(FlowGraphCompiler* compiler, | 698 static void EmitLoadIndexedPolymorphic(FlowGraphCompiler* compiler, |
| 698 LoadIndexedComp* comp) { | 699 LoadIndexedComp* comp) { |
| 699 Label* deopt = compiler->AddDeoptStub(comp->deopt_id(), | 700 Label* deopt = compiler->AddDeoptStub(comp->deopt_id(), |
| 700 comp->token_pos(), | 701 comp->token_pos(), |
| 701 comp->try_index(), | 702 comp->try_index(), |
| 702 kDeoptLoadIndexedPolymorphic); | 703 kDeoptLoadIndexedPolymorphic); |
| 703 ASSERT(comp->ic_data()->NumberOfChecks() > 0); | 704 ASSERT(comp->ic_data()->NumberOfChecks() > 0); |
| 704 ASSERT(comp->HasICData()); | 705 ASSERT(comp->HasICData()); |
| 705 const ICData& ic_data = *comp->ic_data(); | 706 const ICData& ic_data = *comp->ic_data(); |
| 706 ASSERT(ic_data.num_args_tested() == 1); | 707 ASSERT(ic_data.num_args_tested() == 1); |
| 707 // No indexed access on Smi. | 708 // No indexed access on Smi. |
| 708 ASSERT(ic_data.GetReceiverClassIdAt(0) != kSmi); | 709 ASSERT(ic_data.GetReceiverClassIdAt(0) != kSmiCid); |
| 709 // Load receiver into RAX. | 710 // Load receiver into RAX. |
| 710 const intptr_t kNumArguments = 2; | 711 const intptr_t kNumArguments = 2; |
| 711 __ movq(RAX, Address(RSP, (kNumArguments - 1) * kWordSize)); | 712 __ movq(RAX, Address(RSP, (kNumArguments - 1) * kWordSize)); |
| 712 __ testq(RAX, Immediate(kSmiTagMask)); | 713 __ testq(RAX, Immediate(kSmiTagMask)); |
| 713 __ j(ZERO, deopt); | 714 __ j(ZERO, deopt); |
| 714 __ LoadClassId(RDI, RAX); | 715 __ LoadClassId(RDI, RAX); |
| 715 compiler->EmitTestAndCall(ic_data, | 716 compiler->EmitTestAndCall(ic_data, |
| 716 RDI, // Class id register. | 717 RDI, // Class id register. |
| 717 kNumArguments, | 718 kNumArguments, |
| 718 Array::Handle(), // No named arguments. | 719 Array::Handle(), // No named arguments. |
| 719 deopt, // Deoptimize target. | 720 deopt, // Deoptimize target. |
| 720 NULL, // Fallthrough when done. | 721 NULL, // Fallthrough when done. |
| 721 comp->deopt_id(), | 722 comp->deopt_id(), |
| 722 comp->token_pos(), | 723 comp->token_pos(), |
| 723 comp->try_index()); | 724 comp->try_index()); |
| 724 } | 725 } |
| 725 | 726 |
| 726 | 727 |
| 727 void LoadIndexedComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 728 void LoadIndexedComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 728 if (receiver_type() == kIllegalObjectKind) { | 729 if (receiver_type() == kIllegalCid) { |
| 729 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { | 730 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { |
| 730 EmitLoadIndexedPolymorphic(compiler, this); | 731 EmitLoadIndexedPolymorphic(compiler, this); |
| 731 } else { | 732 } else { |
| 732 compiler->EmitLoadIndexedGeneric(this); | 733 compiler->EmitLoadIndexedGeneric(this); |
| 733 } | 734 } |
| 734 ASSERT(locs()->out().reg() == RAX); | 735 ASSERT(locs()->out().reg() == RAX); |
| 735 return; | 736 return; |
| 736 } | 737 } |
| 737 | 738 |
| 738 Register receiver = locs()->in(0).reg(); | 739 Register receiver = locs()->in(0).reg(); |
| 739 Register index = locs()->in(1).reg(); | 740 Register index = locs()->in(1).reg(); |
| 740 Register result = locs()->out().reg(); | 741 Register result = locs()->out().reg(); |
| 741 | 742 |
| 742 const DeoptReasonId deopt_reason = (receiver_type() == kGrowableObjectArray) ? | 743 const DeoptReasonId deopt_reason = |
| 744 (receiver_type() == kGrowableObjectArrayCid) ? |
| 743 kDeoptLoadIndexedGrowableArray : kDeoptLoadIndexedFixedArray; | 745 kDeoptLoadIndexedGrowableArray : kDeoptLoadIndexedFixedArray; |
| 744 | 746 |
| 745 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 747 Label* deopt = compiler->AddDeoptStub(deopt_id(), |
| 746 token_pos(), | 748 token_pos(), |
| 747 try_index(), | 749 try_index(), |
| 748 deopt_reason, | 750 deopt_reason, |
| 749 receiver, | 751 receiver, |
| 750 index); | 752 index); |
| 751 | 753 |
| 752 __ testq(receiver, Immediate(kSmiTagMask)); // Deoptimize if Smi. | 754 __ testq(receiver, Immediate(kSmiTagMask)); // Deoptimize if Smi. |
| 753 __ j(ZERO, deopt); | 755 __ j(ZERO, deopt); |
| 754 __ CompareClassId(receiver, receiver_type()); | 756 __ CompareClassId(receiver, receiver_type()); |
| 755 __ j(NOT_EQUAL, deopt); | 757 __ j(NOT_EQUAL, deopt); |
| 756 | 758 |
| 757 __ testq(index, Immediate(kSmiTagMask)); | 759 __ testq(index, Immediate(kSmiTagMask)); |
| 758 __ j(NOT_ZERO, deopt); | 760 __ j(NOT_ZERO, deopt); |
| 759 | 761 |
| 760 switch (receiver_type()) { | 762 switch (receiver_type()) { |
| 761 case kArray: | 763 case kArrayCid: |
| 762 case kImmutableArray: | 764 case kImmutableArrayCid: |
| 763 __ cmpq(index, FieldAddress(receiver, Array::length_offset())); | 765 __ cmpq(index, FieldAddress(receiver, Array::length_offset())); |
| 764 __ j(ABOVE_EQUAL, deopt); | 766 __ j(ABOVE_EQUAL, deopt); |
| 765 // Note that index is Smi, i.e, times 4. | 767 // Note that index is Smi, i.e, times 4. |
| 766 ASSERT(kSmiTagShift == 1); | 768 ASSERT(kSmiTagShift == 1); |
| 767 __ movq(result, FieldAddress(receiver, index, TIMES_4, sizeof(RawArray))); | 769 __ movq(result, FieldAddress(receiver, index, TIMES_4, sizeof(RawArray))); |
| 768 break; | 770 break; |
| 769 | 771 |
| 770 case kGrowableObjectArray: { | 772 case kGrowableObjectArrayCid: { |
| 771 Register temp = locs()->temp(0).reg(); | 773 Register temp = locs()->temp(0).reg(); |
| 772 | 774 |
| 773 __ cmpq(index, | 775 __ cmpq(index, |
| 774 FieldAddress(receiver, GrowableObjectArray::length_offset())); | 776 FieldAddress(receiver, GrowableObjectArray::length_offset())); |
| 775 __ j(ABOVE_EQUAL, deopt); | 777 __ j(ABOVE_EQUAL, deopt); |
| 776 __ movq(temp, FieldAddress(receiver, GrowableObjectArray::data_offset())); | 778 __ movq(temp, FieldAddress(receiver, GrowableObjectArray::data_offset())); |
| 777 // Note that index is Smi, i.e, times 4. | 779 // Note that index is Smi, i.e, times 4. |
| 778 ASSERT(kSmiTagShift == 1); | 780 ASSERT(kSmiTagShift == 1); |
| 779 __ movq(result, FieldAddress(temp, index, TIMES_4, sizeof(RawArray))); | 781 __ movq(result, FieldAddress(temp, index, TIMES_4, sizeof(RawArray))); |
| 780 break; | 782 break; |
| 781 } | 783 } |
| 782 | 784 |
| 783 default: | 785 default: |
| 784 UNREACHABLE(); | 786 UNREACHABLE(); |
| 785 break; | 787 break; |
| 786 } | 788 } |
| 787 } | 789 } |
| 788 | 790 |
| 789 | 791 |
| 790 LocationSummary* StoreIndexedComp::MakeLocationSummary() const { | 792 LocationSummary* StoreIndexedComp::MakeLocationSummary() const { |
| 791 const intptr_t kNumInputs = 3; | 793 const intptr_t kNumInputs = 3; |
| 792 if (receiver_type() == kGrowableObjectArray) { | 794 if (receiver_type() == kGrowableObjectArrayCid) { |
| 793 const intptr_t kNumTemps = 1; | 795 const intptr_t kNumTemps = 1; |
| 794 LocationSummary* locs = | 796 LocationSummary* locs = |
| 795 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 797 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 796 locs->set_in(0, Location::RequiresRegister()); | 798 locs->set_in(0, Location::RequiresRegister()); |
| 797 locs->set_in(1, Location::RequiresRegister()); | 799 locs->set_in(1, Location::RequiresRegister()); |
| 798 locs->set_in(2, Location::RequiresRegister()); | 800 locs->set_in(2, Location::RequiresRegister()); |
| 799 locs->set_temp(0, Location::RequiresRegister()); | 801 locs->set_temp(0, Location::RequiresRegister()); |
| 800 locs->set_out(Location::NoLocation()); | 802 locs->set_out(Location::NoLocation()); |
| 801 return locs; | 803 return locs; |
| 802 } else if (receiver_type() == kArray) { | 804 } else if (receiver_type() == kArrayCid) { |
| 803 return LocationSummary::Make(kNumInputs, | 805 return LocationSummary::Make(kNumInputs, |
| 804 Location::NoLocation(), | 806 Location::NoLocation(), |
| 805 LocationSummary::kNoCall); | 807 LocationSummary::kNoCall); |
| 806 } else { | 808 } else { |
| 807 ASSERT(receiver_type() == kIllegalObjectKind); | 809 ASSERT(receiver_type() == kIllegalCid); |
| 808 return MakeCallSummary(); | 810 return MakeCallSummary(); |
| 809 } | 811 } |
| 810 } | 812 } |
| 811 | 813 |
| 812 | 814 |
| 813 static void EmitStoreIndexedGeneric(FlowGraphCompiler* compiler, | 815 static void EmitStoreIndexedGeneric(FlowGraphCompiler* compiler, |
| 814 StoreIndexedComp* comp) { | 816 StoreIndexedComp* comp) { |
| 815 const String& function_name = | 817 const String& function_name = |
| 816 String::ZoneHandle(Symbols::New(Token::Str(Token::kASSIGN_INDEX))); | 818 String::ZoneHandle(Symbols::New(Token::Str(Token::kASSIGN_INDEX))); |
| 817 | 819 |
| (...skipping 18 matching lines...) Expand all Loading... |
| 836 StoreIndexedComp* comp) { | 838 StoreIndexedComp* comp) { |
| 837 Label* deopt = compiler->AddDeoptStub(comp->deopt_id(), | 839 Label* deopt = compiler->AddDeoptStub(comp->deopt_id(), |
| 838 comp->token_pos(), | 840 comp->token_pos(), |
| 839 comp->try_index(), | 841 comp->try_index(), |
| 840 kDeoptStoreIndexedPolymorphic); | 842 kDeoptStoreIndexedPolymorphic); |
| 841 ASSERT(comp->ic_data()->NumberOfChecks() > 0); | 843 ASSERT(comp->ic_data()->NumberOfChecks() > 0); |
| 842 ASSERT(comp->HasICData()); | 844 ASSERT(comp->HasICData()); |
| 843 const ICData& ic_data = *comp->ic_data(); | 845 const ICData& ic_data = *comp->ic_data(); |
| 844 ASSERT(ic_data.num_args_tested() == 1); | 846 ASSERT(ic_data.num_args_tested() == 1); |
| 845 // No indexed access on Smi. | 847 // No indexed access on Smi. |
| 846 ASSERT(ic_data.GetReceiverClassIdAt(0) != kSmi); | 848 ASSERT(ic_data.GetReceiverClassIdAt(0) != kSmiCid); |
| 847 // Load receiver into RAX. | 849 // Load receiver into RAX. |
| 848 const intptr_t kNumArguments = 3; | 850 const intptr_t kNumArguments = 3; |
| 849 __ movq(RAX, Address(RSP, (kNumArguments - 1) * kWordSize)); | 851 __ movq(RAX, Address(RSP, (kNumArguments - 1) * kWordSize)); |
| 850 __ testq(RAX, Immediate(kSmiTagMask)); | 852 __ testq(RAX, Immediate(kSmiTagMask)); |
| 851 __ j(ZERO, deopt); | 853 __ j(ZERO, deopt); |
| 852 __ LoadClassId(RDI, RAX); | 854 __ LoadClassId(RDI, RAX); |
| 853 compiler->EmitTestAndCall(ic_data, | 855 compiler->EmitTestAndCall(ic_data, |
| 854 RDI, // Class id register. | 856 RDI, // Class id register. |
| 855 kNumArguments, | 857 kNumArguments, |
| 856 Array::Handle(), // No named arguments. | 858 Array::Handle(), // No named arguments. |
| 857 deopt, // deoptimize label. | 859 deopt, // deoptimize label. |
| 858 NULL, // fallthrough when done. | 860 NULL, // fallthrough when done. |
| 859 comp->deopt_id(), | 861 comp->deopt_id(), |
| 860 comp->token_pos(), | 862 comp->token_pos(), |
| 861 comp->try_index()); | 863 comp->try_index()); |
| 862 } | 864 } |
| 863 | 865 |
| 864 | 866 |
| 865 void StoreIndexedComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 867 void StoreIndexedComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 866 if (receiver_type() == kIllegalObjectKind) { | 868 if (receiver_type() == kIllegalCid) { |
| 867 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { | 869 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { |
| 868 EmitStoreIndexedPolymorphic(compiler, this); | 870 EmitStoreIndexedPolymorphic(compiler, this); |
| 869 } else { | 871 } else { |
| 870 EmitStoreIndexedGeneric(compiler, this); | 872 EmitStoreIndexedGeneric(compiler, this); |
| 871 } | 873 } |
| 872 return; | 874 return; |
| 873 } | 875 } |
| 874 | 876 |
| 875 Register receiver = locs()->in(0).reg(); | 877 Register receiver = locs()->in(0).reg(); |
| 876 Register index = locs()->in(1).reg(); | 878 Register index = locs()->in(1).reg(); |
| 877 Register value = locs()->in(2).reg(); | 879 Register value = locs()->in(2).reg(); |
| 878 | 880 |
| 879 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 881 Label* deopt = compiler->AddDeoptStub(deopt_id(), |
| 880 token_pos(), | 882 token_pos(), |
| 881 try_index(), | 883 try_index(), |
| 882 kDeoptStoreIndexed, | 884 kDeoptStoreIndexed, |
| 883 receiver, | 885 receiver, |
| 884 index, | 886 index, |
| 885 value); | 887 value); |
| 886 | 888 |
| 887 __ testq(receiver, Immediate(kSmiTagMask)); // Deoptimize if Smi. | 889 __ testq(receiver, Immediate(kSmiTagMask)); // Deoptimize if Smi. |
| 888 __ j(ZERO, deopt); | 890 __ j(ZERO, deopt); |
| 889 __ CompareClassId(receiver, receiver_type()); | 891 __ CompareClassId(receiver, receiver_type()); |
| 890 __ j(NOT_EQUAL, deopt); | 892 __ j(NOT_EQUAL, deopt); |
| 891 | 893 |
| 892 __ testq(index, Immediate(kSmiTagMask)); | 894 __ testq(index, Immediate(kSmiTagMask)); |
| 893 __ j(NOT_ZERO, deopt); | 895 __ j(NOT_ZERO, deopt); |
| 894 | 896 |
| 895 switch (receiver_type()) { | 897 switch (receiver_type()) { |
| 896 case kArray: | 898 case kArrayCid: |
| 897 case kImmutableArray: | 899 case kImmutableArrayCid: |
| 898 __ cmpq(index, FieldAddress(receiver, Array::length_offset())); | 900 __ cmpq(index, FieldAddress(receiver, Array::length_offset())); |
| 899 __ j(ABOVE_EQUAL, deopt); | 901 __ j(ABOVE_EQUAL, deopt); |
| 900 // Note that index is Smi, i.e, times 4. | 902 // Note that index is Smi, i.e, times 4. |
| 901 ASSERT(kSmiTagShift == 1); | 903 ASSERT(kSmiTagShift == 1); |
| 902 __ StoreIntoObject(receiver, | 904 __ StoreIntoObject(receiver, |
| 903 FieldAddress(receiver, index, TIMES_4, sizeof(RawArray)), | 905 FieldAddress(receiver, index, TIMES_4, sizeof(RawArray)), |
| 904 value); | 906 value); |
| 905 break; | 907 break; |
| 906 | 908 |
| 907 case kGrowableObjectArray: { | 909 case kGrowableObjectArrayCid: { |
| 908 Register temp = locs()->temp(0).reg(); | 910 Register temp = locs()->temp(0).reg(); |
| 909 __ cmpq(index, | 911 __ cmpq(index, |
| 910 FieldAddress(receiver, GrowableObjectArray::length_offset())); | 912 FieldAddress(receiver, GrowableObjectArray::length_offset())); |
| 911 __ j(ABOVE_EQUAL, deopt); | 913 __ j(ABOVE_EQUAL, deopt); |
| 912 __ movq(temp, FieldAddress(receiver, GrowableObjectArray::data_offset())); | 914 __ movq(temp, FieldAddress(receiver, GrowableObjectArray::data_offset())); |
| 913 // Note that index is Smi, i.e, times 4. | 915 // Note that index is Smi, i.e, times 4. |
| 914 ASSERT(kSmiTagShift == 1); | 916 ASSERT(kSmiTagShift == 1); |
| 915 __ StoreIntoObject(temp, | 917 __ StoreIntoObject(temp, |
| 916 FieldAddress(temp, index, TIMES_4, sizeof(RawArray)), | 918 FieldAddress(temp, index, TIMES_4, sizeof(RawArray)), |
| 917 value); | 919 value); |
| (...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1121 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); | 1123 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); |
| 1122 } | 1124 } |
| 1123 // Instantiate non-null type arguments. | 1125 // Instantiate non-null type arguments. |
| 1124 if (type_arguments().IsUninstantiatedIdentity()) { | 1126 if (type_arguments().IsUninstantiatedIdentity()) { |
| 1125 // Check if the instantiator type argument vector is a TypeArguments of a | 1127 // Check if the instantiator type argument vector is a TypeArguments of a |
| 1126 // matching length and, if so, use it as the instantiated type_arguments. | 1128 // matching length and, if so, use it as the instantiated type_arguments. |
| 1127 // No need to check the instantiator ('instantiator_reg') for null here, | 1129 // No need to check the instantiator ('instantiator_reg') for null here, |
| 1128 // because a null instantiator will have the wrong class (Null instead of | 1130 // because a null instantiator will have the wrong class (Null instead of |
| 1129 // TypeArguments). | 1131 // TypeArguments). |
| 1130 Label type_arguments_uninstantiated; | 1132 Label type_arguments_uninstantiated; |
| 1131 __ CompareClassId(instantiator_reg, kTypeArguments); | 1133 __ CompareClassId(instantiator_reg, kTypeArgumentsCid); |
| 1132 __ j(NOT_EQUAL, &type_arguments_uninstantiated, Assembler::kNearJump); | 1134 __ j(NOT_EQUAL, &type_arguments_uninstantiated, Assembler::kNearJump); |
| 1133 __ cmpq(FieldAddress(instantiator_reg, TypeArguments::length_offset()), | 1135 __ cmpq(FieldAddress(instantiator_reg, TypeArguments::length_offset()), |
| 1134 Immediate(Smi::RawValue(len))); | 1136 Immediate(Smi::RawValue(len))); |
| 1135 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); | 1137 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); |
| 1136 __ Bind(&type_arguments_uninstantiated); | 1138 __ Bind(&type_arguments_uninstantiated); |
| 1137 } | 1139 } |
| 1138 // A runtime call to instantiate the type arguments is required. | 1140 // A runtime call to instantiate the type arguments is required. |
| 1139 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 1141 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
| 1140 __ PushObject(type_arguments()); | 1142 __ PushObject(type_arguments()); |
| 1141 __ pushq(instantiator_reg); // Push instantiator type arguments. | 1143 __ pushq(instantiator_reg); // Push instantiator type arguments. |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1182 __ cmpq(instantiator_reg, raw_null); | 1184 __ cmpq(instantiator_reg, raw_null); |
| 1183 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); | 1185 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); |
| 1184 } | 1186 } |
| 1185 // Instantiate non-null type arguments. | 1187 // Instantiate non-null type arguments. |
| 1186 if (type_arguments().IsUninstantiatedIdentity()) { | 1188 if (type_arguments().IsUninstantiatedIdentity()) { |
| 1187 // Check if the instantiator type argument vector is a TypeArguments of a | 1189 // Check if the instantiator type argument vector is a TypeArguments of a |
| 1188 // matching length and, if so, use it as the instantiated type_arguments. | 1190 // matching length and, if so, use it as the instantiated type_arguments. |
| 1189 // No need to check instantiator_reg for null here, because a null | 1191 // No need to check instantiator_reg for null here, because a null |
| 1190 // instantiator will have the wrong class (Null instead of TypeArguments). | 1192 // instantiator will have the wrong class (Null instead of TypeArguments). |
| 1191 Label type_arguments_uninstantiated; | 1193 Label type_arguments_uninstantiated; |
| 1192 __ CompareClassId(instantiator_reg, kTypeArguments); | 1194 __ CompareClassId(instantiator_reg, kTypeArgumentsCid); |
| 1193 __ j(NOT_EQUAL, &type_arguments_uninstantiated, Assembler::kNearJump); | 1195 __ j(NOT_EQUAL, &type_arguments_uninstantiated, Assembler::kNearJump); |
| 1194 Immediate arguments_length = | 1196 Immediate arguments_length = |
| 1195 Immediate(Smi::RawValue(type_arguments().Length())); | 1197 Immediate(Smi::RawValue(type_arguments().Length())); |
| 1196 __ cmpq(FieldAddress(instantiator_reg, TypeArguments::length_offset()), | 1198 __ cmpq(FieldAddress(instantiator_reg, TypeArguments::length_offset()), |
| 1197 arguments_length); | 1199 arguments_length); |
| 1198 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); | 1200 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); |
| 1199 __ Bind(&type_arguments_uninstantiated); | 1201 __ Bind(&type_arguments_uninstantiated); |
| 1200 } | 1202 } |
| 1201 // In the non-factory case, we rely on the allocation stub to | 1203 // In the non-factory case, we rely on the allocation stub to |
| 1202 // instantiate the type arguments. | 1204 // instantiate the type arguments. |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1249 // TODO(regis): The following emitted code is duplicated in | 1251 // TODO(regis): The following emitted code is duplicated in |
| 1250 // VisitExtractConstructorTypeArguments above. The reason is that the code | 1252 // VisitExtractConstructorTypeArguments above. The reason is that the code |
| 1251 // is split between two computations, so that each one produces a | 1253 // is split between two computations, so that each one produces a |
| 1252 // single value, rather than producing a pair of values. | 1254 // single value, rather than producing a pair of values. |
| 1253 // If this becomes an issue, we should expose these tests at the IL level. | 1255 // If this becomes an issue, we should expose these tests at the IL level. |
| 1254 | 1256 |
| 1255 // Check if the instantiator type argument vector is a TypeArguments of a | 1257 // Check if the instantiator type argument vector is a TypeArguments of a |
| 1256 // matching length and, if so, use it as the instantiated type_arguments. | 1258 // matching length and, if so, use it as the instantiated type_arguments. |
| 1257 // No need to check the instantiator (RAX) for null here, because a null | 1259 // No need to check the instantiator (RAX) for null here, because a null |
| 1258 // instantiator will have the wrong class (Null instead of TypeArguments). | 1260 // instantiator will have the wrong class (Null instead of TypeArguments). |
| 1259 __ CompareClassId(instantiator_reg, kTypeArguments); | 1261 __ CompareClassId(instantiator_reg, kTypeArgumentsCid); |
| 1260 __ j(NOT_EQUAL, &done, Assembler::kNearJump); | 1262 __ j(NOT_EQUAL, &done, Assembler::kNearJump); |
| 1261 Immediate arguments_length = | 1263 Immediate arguments_length = |
| 1262 Immediate(Smi::RawValue(type_arguments().Length())); | 1264 Immediate(Smi::RawValue(type_arguments().Length())); |
| 1263 __ cmpq(FieldAddress(instantiator_reg, TypeArguments::length_offset()), | 1265 __ cmpq(FieldAddress(instantiator_reg, TypeArguments::length_offset()), |
| 1264 arguments_length); | 1266 arguments_length); |
| 1265 __ j(NOT_EQUAL, &done, Assembler::kNearJump); | 1267 __ j(NOT_EQUAL, &done, Assembler::kNearJump); |
| 1266 // The instantiator was used in VisitExtractConstructorTypeArguments as the | 1268 // The instantiator was used in VisitExtractConstructorTypeArguments as the |
| 1267 // instantiated type arguments, no proper instantiator needed. | 1269 // instantiated type arguments, no proper instantiator needed. |
| 1268 __ movq(instantiator_reg, | 1270 __ movq(instantiator_reg, |
| 1269 Immediate(Smi::RawValue(StubCode::kNoInstantiator))); | 1271 Immediate(Smi::RawValue(StubCode::kNoInstantiator))); |
| (...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1548 __ shlq(left, right_temp); | 1550 __ shlq(left, right_temp); |
| 1549 __ sarq(left, right_temp); | 1551 __ sarq(left, right_temp); |
| 1550 __ cmpq(left, temp); | 1552 __ cmpq(left, temp); |
| 1551 __ j(NOT_EQUAL, &call_method, Assembler::kNearJump); // Overflow. | 1553 __ j(NOT_EQUAL, &call_method, Assembler::kNearJump); // Overflow. |
| 1552 // Shift for result now we know there is no overflow. | 1554 // Shift for result now we know there is no overflow. |
| 1553 __ shlq(left, right_temp); | 1555 __ shlq(left, right_temp); |
| 1554 __ jmp(&done); | 1556 __ jmp(&done); |
| 1555 { | 1557 { |
| 1556 __ Bind(&call_method); | 1558 __ Bind(&call_method); |
| 1557 Function& target = Function::ZoneHandle( | 1559 Function& target = Function::ZoneHandle( |
| 1558 comp->ic_data()->GetTargetForReceiverClassId(kSmi)); | 1560 comp->ic_data()->GetTargetForReceiverClassId(kSmiCid)); |
| 1559 ASSERT(!target.IsNull()); | 1561 ASSERT(!target.IsNull()); |
| 1560 const intptr_t kArgumentCount = 2; | 1562 const intptr_t kArgumentCount = 2; |
| 1561 __ pushq(temp); | 1563 __ pushq(temp); |
| 1562 __ pushq(right); | 1564 __ pushq(right); |
| 1563 compiler->GenerateStaticCall(comp->instance_call()->deopt_id(), | 1565 compiler->GenerateStaticCall(comp->instance_call()->deopt_id(), |
| 1564 comp->instance_call()->token_pos(), | 1566 comp->instance_call()->token_pos(), |
| 1565 comp->instance_call()->try_index(), | 1567 comp->instance_call()->try_index(), |
| 1566 target, | 1568 target, |
| 1567 kArgumentCount, | 1569 kArgumentCount, |
| 1568 Array::Handle()); // No argument names. | 1570 Array::Handle()); // No argument names. |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1610 comp->instance_call()->token_pos(), | 1612 comp->instance_call()->token_pos(), |
| 1611 comp->instance_call()->try_index(), | 1613 comp->instance_call()->try_index(), |
| 1612 kDeoptMintBinaryOp, | 1614 kDeoptMintBinaryOp, |
| 1613 left, | 1615 left, |
| 1614 right); | 1616 right); |
| 1615 Label mint_static_call, smi_static_call, non_smi, smi_smi, done; | 1617 Label mint_static_call, smi_static_call, non_smi, smi_smi, done; |
| 1616 __ testq(left, Immediate(kSmiTagMask)); // Is receiver Smi? | 1618 __ testq(left, Immediate(kSmiTagMask)); // Is receiver Smi? |
| 1617 __ j(NOT_ZERO, &non_smi); | 1619 __ j(NOT_ZERO, &non_smi); |
| 1618 __ testq(right, Immediate(kSmiTagMask)); // Is argument Smi? | 1620 __ testq(right, Immediate(kSmiTagMask)); // Is argument Smi? |
| 1619 __ j(ZERO, &smi_smi); | 1621 __ j(ZERO, &smi_smi); |
| 1620 __ CompareClassId(right, kMint); // Is argument Mint? | 1622 __ CompareClassId(right, kMintCid); // Is argument Mint? |
| 1621 __ j(NOT_EQUAL, deopt); // Argument neither Smi nor Mint. | 1623 __ j(NOT_EQUAL, deopt); // Argument neither Smi nor Mint. |
| 1622 __ cmpq(left, Immediate(0)); | 1624 __ cmpq(left, Immediate(0)); |
| 1623 __ j(LESS, &smi_static_call); // Negative Smi receiver, Mint argument. | 1625 __ j(LESS, &smi_static_call); // Negative Smi receiver, Mint argument. |
| 1624 | 1626 |
| 1625 // Positive Smi receiver, Mint argument. | 1627 // Positive Smi receiver, Mint argument. |
| 1626 // Load lower argument Mint word, convert to Smi. It is OK to loose bits. | 1628 // Load lower argument Mint word, convert to Smi. It is OK to loose bits. |
| 1627 __ movq(right, FieldAddress(right, Mint::value_offset())); | 1629 __ movq(right, FieldAddress(right, Mint::value_offset())); |
| 1628 __ SmiTag(right); | 1630 __ SmiTag(right); |
| 1629 __ andq(result, right); | 1631 __ andq(result, right); |
| 1630 __ jmp(&done); | 1632 __ jmp(&done); |
| 1631 | 1633 |
| 1632 __ Bind(&non_smi); // Receiver is non-Smi. | 1634 __ Bind(&non_smi); // Receiver is non-Smi. |
| 1633 __ CompareClassId(left, kMint); // Is receiver Mint? | 1635 __ CompareClassId(left, kMintCid); // Is receiver Mint? |
| 1634 __ j(NOT_EQUAL, deopt); // Receiver neither Smi nor Mint. | 1636 __ j(NOT_EQUAL, deopt); // Receiver neither Smi nor Mint. |
| 1635 __ testq(right, Immediate(kSmiTagMask)); // Is argument Smi? | 1637 __ testq(right, Immediate(kSmiTagMask)); // Is argument Smi? |
| 1636 __ j(NOT_ZERO, &mint_static_call); // Mint receiver, non-Smi argument. | 1638 __ j(NOT_ZERO, &mint_static_call); // Mint receiver, non-Smi argument. |
| 1637 __ cmpq(right, Immediate(0)); | 1639 __ cmpq(right, Immediate(0)); |
| 1638 __ j(LESS, &mint_static_call); // Mint receiver, negative Smi argument. | 1640 __ j(LESS, &mint_static_call); // Mint receiver, negative Smi argument. |
| 1639 | 1641 |
| 1640 // Mint receiver, positive Smi argument. | 1642 // Mint receiver, positive Smi argument. |
| 1641 // Load lower receiver Mint word, convert to Smi. It is OK to loose bits. | 1643 // Load lower receiver Mint word, convert to Smi. It is OK to loose bits. |
| 1642 __ movq(result, FieldAddress(left, Mint::value_offset())); | 1644 __ movq(result, FieldAddress(left, Mint::value_offset())); |
| 1643 __ SmiTag(result); | 1645 __ SmiTag(result); |
| 1644 __ Bind(&smi_smi); | 1646 __ Bind(&smi_smi); |
| 1645 __ andq(result, right); | 1647 __ andq(result, right); |
| 1646 __ jmp(&done); | 1648 __ jmp(&done); |
| 1647 | 1649 |
| 1648 __ Bind(&smi_static_call); | 1650 __ Bind(&smi_static_call); |
| 1649 { | 1651 { |
| 1650 Function& target = Function::ZoneHandle( | 1652 Function& target = Function::ZoneHandle( |
| 1651 comp->ic_data()->GetTargetForReceiverClassId(kSmi)); | 1653 comp->ic_data()->GetTargetForReceiverClassId(kSmiCid)); |
| 1652 if (target.IsNull()) { | 1654 if (target.IsNull()) { |
| 1653 __ jmp(deopt); | 1655 __ jmp(deopt); |
| 1654 } else { | 1656 } else { |
| 1655 __ pushq(left); | 1657 __ pushq(left); |
| 1656 __ pushq(right); | 1658 __ pushq(right); |
| 1657 compiler->GenerateStaticCall(comp->instance_call()->deopt_id(), | 1659 compiler->GenerateStaticCall(comp->instance_call()->deopt_id(), |
| 1658 comp->instance_call()->token_pos(), | 1660 comp->instance_call()->token_pos(), |
| 1659 comp->instance_call()->try_index(), | 1661 comp->instance_call()->try_index(), |
| 1660 target, | 1662 target, |
| 1661 comp->instance_call()->ArgumentCount(), | 1663 comp->instance_call()->ArgumentCount(), |
| 1662 comp->instance_call()->argument_names()); | 1664 comp->instance_call()->argument_names()); |
| 1663 ASSERT(result == RAX); | 1665 ASSERT(result == RAX); |
| 1664 __ jmp(&done); | 1666 __ jmp(&done); |
| 1665 } | 1667 } |
| 1666 } | 1668 } |
| 1667 | 1669 |
| 1668 __ Bind(&mint_static_call); | 1670 __ Bind(&mint_static_call); |
| 1669 { | 1671 { |
| 1670 Function& target = Function::ZoneHandle( | 1672 Function& target = Function::ZoneHandle( |
| 1671 comp->ic_data()->GetTargetForReceiverClassId(kMint)); | 1673 comp->ic_data()->GetTargetForReceiverClassId(kMintCid)); |
| 1672 if (target.IsNull()) { | 1674 if (target.IsNull()) { |
| 1673 __ jmp(deopt); | 1675 __ jmp(deopt); |
| 1674 } else { | 1676 } else { |
| 1675 __ pushq(left); | 1677 __ pushq(left); |
| 1676 __ pushq(right); | 1678 __ pushq(right); |
| 1677 compiler->GenerateStaticCall(comp->instance_call()->deopt_id(), | 1679 compiler->GenerateStaticCall(comp->instance_call()->deopt_id(), |
| 1678 comp->instance_call()->token_pos(), | 1680 comp->instance_call()->token_pos(), |
| 1679 comp->instance_call()->try_index(), | 1681 comp->instance_call()->try_index(), |
| 1680 target, | 1682 target, |
| 1681 comp->instance_call()->ArgumentCount(), | 1683 comp->instance_call()->ArgumentCount(), |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1777 ic_data.GetOneClassCheckAt(0, &test_class_id, &target); | 1779 ic_data.GetOneClassCheckAt(0, &test_class_id, &target); |
| 1778 | 1780 |
| 1779 Register value = locs()->in(0).reg(); | 1781 Register value = locs()->in(0).reg(); |
| 1780 Register result = locs()->out().reg(); | 1782 Register result = locs()->out().reg(); |
| 1781 ASSERT(value == result); | 1783 ASSERT(value == result); |
| 1782 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), | 1784 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), |
| 1783 instance_call()->token_pos(), | 1785 instance_call()->token_pos(), |
| 1784 instance_call()->try_index(), | 1786 instance_call()->try_index(), |
| 1785 kDeoptUnaryOp, | 1787 kDeoptUnaryOp, |
| 1786 value); | 1788 value); |
| 1787 if (test_class_id == kSmi) { | 1789 if (test_class_id == kSmiCid) { |
| 1788 __ testq(value, Immediate(kSmiTagMask)); | 1790 __ testq(value, Immediate(kSmiTagMask)); |
| 1789 __ j(NOT_ZERO, deopt); | 1791 __ j(NOT_ZERO, deopt); |
| 1790 switch (op_kind()) { | 1792 switch (op_kind()) { |
| 1791 case Token::kNEGATE: | 1793 case Token::kNEGATE: |
| 1792 __ negq(value); | 1794 __ negq(value); |
| 1793 __ j(OVERFLOW, deopt); | 1795 __ j(OVERFLOW, deopt); |
| 1794 break; | 1796 break; |
| 1795 case Token::kBIT_NOT: | 1797 case Token::kBIT_NOT: |
| 1796 __ notq(value); | 1798 __ notq(value); |
| 1797 __ andq(value, Immediate(~kSmiTagMask)); // Remove inverted smi-tag. | 1799 __ andq(value, Immediate(~kSmiTagMask)); // Remove inverted smi-tag. |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1829 ic_data.GetOneClassCheckAt(0, &test_class_id, &target); | 1831 ic_data.GetOneClassCheckAt(0, &test_class_id, &target); |
| 1830 | 1832 |
| 1831 Register value = locs()->in(0).reg(); | 1833 Register value = locs()->in(0).reg(); |
| 1832 Register result = locs()->out().reg(); | 1834 Register result = locs()->out().reg(); |
| 1833 ASSERT(value == result); | 1835 ASSERT(value == result); |
| 1834 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), | 1836 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), |
| 1835 instance_call()->token_pos(), | 1837 instance_call()->token_pos(), |
| 1836 instance_call()->try_index(), | 1838 instance_call()->try_index(), |
| 1837 kDeoptUnaryOp, | 1839 kDeoptUnaryOp, |
| 1838 value); | 1840 value); |
| 1839 if (test_class_id == kDouble) { | 1841 if (test_class_id == kDoubleCid) { |
| 1840 Register temp = locs()->temp(0).reg(); | 1842 Register temp = locs()->temp(0).reg(); |
| 1841 __ testq(value, Immediate(kSmiTagMask)); | 1843 __ testq(value, Immediate(kSmiTagMask)); |
| 1842 __ j(ZERO, deopt); // Smi. | 1844 __ j(ZERO, deopt); // Smi. |
| 1843 __ CompareClassId(value, kDouble); | 1845 __ CompareClassId(value, kDoubleCid); |
| 1844 __ j(NOT_EQUAL, deopt); | 1846 __ j(NOT_EQUAL, deopt); |
| 1845 // Allocate result object. | 1847 // Allocate result object. |
| 1846 const Class& double_class = compiler->double_class(); | 1848 const Class& double_class = compiler->double_class(); |
| 1847 const Code& stub = | 1849 const Code& stub = |
| 1848 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); | 1850 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); |
| 1849 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); | 1851 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); |
| 1850 __ pushq(value); | 1852 __ pushq(value); |
| 1851 compiler->GenerateCall(instance_call()->token_pos(), | 1853 compiler->GenerateCall(instance_call()->token_pos(), |
| 1852 instance_call()->try_index(), | 1854 instance_call()->try_index(), |
| 1853 &label, | 1855 &label, |
| 1854 PcDescriptors::kOther); | 1856 PcDescriptors::kOther); |
| 1855 // Result is in RAX. | 1857 // Result is in RAX. |
| 1856 ASSERT(result != temp); | 1858 ASSERT(result != temp); |
| 1857 __ movq(result, RAX); | 1859 __ movq(result, RAX); |
| 1858 __ popq(temp); | 1860 __ popq(temp); |
| 1859 __ movsd(XMM0, FieldAddress(temp, Double::value_offset())); | 1861 __ movsd(XMM0, FieldAddress(temp, Double::value_offset())); |
| 1860 __ DoubleNegate(XMM0); | 1862 __ DoubleNegate(XMM0); |
| 1861 __ movsd(FieldAddress(result, Double::value_offset()), XMM0); | 1863 __ movsd(FieldAddress(result, Double::value_offset()), XMM0); |
| 1862 } else { | 1864 } else { |
| 1863 UNREACHABLE(); | 1865 UNREACHABLE(); |
| 1864 } | 1866 } |
| 1865 } | 1867 } |
| 1866 | 1868 |
| 1867 | 1869 |
| 1868 LocationSummary* ToDoubleComp::MakeLocationSummary() const { | 1870 LocationSummary* ToDoubleComp::MakeLocationSummary() const { |
| 1869 const intptr_t kNumInputs = 1; | 1871 const intptr_t kNumInputs = 1; |
| 1870 if (from() == kDouble) { | 1872 if (from() == kDoubleCid) { |
| 1871 const intptr_t kNumTemps = 0; | 1873 const intptr_t kNumTemps = 0; |
| 1872 LocationSummary* locs = | 1874 LocationSummary* locs = |
| 1873 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1875 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1874 locs->set_in(0, Location::RequiresRegister()); | 1876 locs->set_in(0, Location::RequiresRegister()); |
| 1875 locs->set_out(Location::SameAsFirstInput()); | 1877 locs->set_out(Location::SameAsFirstInput()); |
| 1876 return locs; | 1878 return locs; |
| 1877 } else { | 1879 } else { |
| 1878 ASSERT(from() == kSmi); | 1880 ASSERT(from() == kSmiCid); |
| 1879 return MakeCallSummary(); // Calls a stub to allocate result. | 1881 return MakeCallSummary(); // Calls a stub to allocate result. |
| 1880 } | 1882 } |
| 1881 } | 1883 } |
| 1882 | 1884 |
| 1883 | 1885 |
| 1884 void ToDoubleComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1886 void ToDoubleComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1885 Register value = (from() == kDouble) ? locs()->in(0).reg() : RBX; | 1887 Register value = (from() == kDoubleCid) ? locs()->in(0).reg() : RBX; |
| 1886 Register result = locs()->out().reg(); | 1888 Register result = locs()->out().reg(); |
| 1887 | 1889 |
| 1888 const DeoptReasonId deopt_reason = (from() == kDouble) ? | 1890 const DeoptReasonId deopt_reason = (from() == kDoubleCid) ? |
| 1889 kDeoptDoubleToDouble : kDeoptIntegerToDouble; | 1891 kDeoptDoubleToDouble : kDeoptIntegerToDouble; |
| 1890 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), | 1892 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), |
| 1891 instance_call()->token_pos(), | 1893 instance_call()->token_pos(), |
| 1892 instance_call()->try_index(), | 1894 instance_call()->try_index(), |
| 1893 deopt_reason, | 1895 deopt_reason, |
| 1894 value); | 1896 value); |
| 1895 | 1897 |
| 1896 if (from() == kDouble) { | 1898 if (from() == kDoubleCid) { |
| 1897 __ testq(value, Immediate(kSmiTagMask)); | 1899 __ testq(value, Immediate(kSmiTagMask)); |
| 1898 __ j(ZERO, deopt); // Deoptimize if Smi. | 1900 __ j(ZERO, deopt); // Deoptimize if Smi. |
| 1899 __ CompareClassId(value, kDouble); | 1901 __ CompareClassId(value, kDoubleCid); |
| 1900 __ j(NOT_EQUAL, deopt); // Deoptimize if not Double. | 1902 __ j(NOT_EQUAL, deopt); // Deoptimize if not Double. |
| 1901 ASSERT(value == result); | 1903 ASSERT(value == result); |
| 1902 return; | 1904 return; |
| 1903 } | 1905 } |
| 1904 | 1906 |
| 1905 ASSERT(from() == kSmi); | 1907 ASSERT(from() == kSmiCid); |
| 1906 | 1908 |
| 1907 const Class& double_class = compiler->double_class(); | 1909 const Class& double_class = compiler->double_class(); |
| 1908 const Code& stub = | 1910 const Code& stub = |
| 1909 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); | 1911 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); |
| 1910 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); | 1912 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); |
| 1911 | 1913 |
| 1912 // TODO(vegorov): allocate box in the driver loop to avoid spilling. | 1914 // TODO(vegorov): allocate box in the driver loop to avoid spilling. |
| 1913 compiler->GenerateCall(instance_call()->token_pos(), | 1915 compiler->GenerateCall(instance_call()->token_pos(), |
| 1914 instance_call()->try_index(), | 1916 instance_call()->try_index(), |
| 1915 &label, | 1917 &label, |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1936 instance_call()->try_index(), | 1938 instance_call()->try_index(), |
| 1937 kDeoptPolymorphicInstanceCallTestFail); | 1939 kDeoptPolymorphicInstanceCallTestFail); |
| 1938 if (!HasICData() || (ic_data()->NumberOfChecks() == 0)) { | 1940 if (!HasICData() || (ic_data()->NumberOfChecks() == 0)) { |
| 1939 __ jmp(deopt); | 1941 __ jmp(deopt); |
| 1940 return; | 1942 return; |
| 1941 } | 1943 } |
| 1942 ASSERT(HasICData()); | 1944 ASSERT(HasICData()); |
| 1943 ASSERT(ic_data()->num_args_tested() == 1); | 1945 ASSERT(ic_data()->num_args_tested() == 1); |
| 1944 Label handle_smi; | 1946 Label handle_smi; |
| 1945 Label* is_smi_label = | 1947 Label* is_smi_label = |
| 1946 ic_data()->GetReceiverClassIdAt(0) == kSmi ? &handle_smi : deopt; | 1948 ic_data()->GetReceiverClassIdAt(0) == kSmiCid ? &handle_smi : deopt; |
| 1947 | 1949 |
| 1948 // Load receiver into RAX. | 1950 // Load receiver into RAX. |
| 1949 __ movq(RAX, | 1951 __ movq(RAX, |
| 1950 Address(RSP, (instance_call()->ArgumentCount() - 1) * kWordSize)); | 1952 Address(RSP, (instance_call()->ArgumentCount() - 1) * kWordSize)); |
| 1951 __ testq(RAX, Immediate(kSmiTagMask)); | 1953 __ testq(RAX, Immediate(kSmiTagMask)); |
| 1952 __ j(ZERO, is_smi_label); | 1954 __ j(ZERO, is_smi_label); |
| 1953 Label done; | 1955 Label done; |
| 1954 __ LoadClassId(RDI, RAX); | 1956 __ LoadClassId(RDI, RAX); |
| 1955 compiler->EmitTestAndCall(*ic_data(), | 1957 compiler->EmitTestAndCall(*ic_data(), |
| 1956 RDI, // Class id register. | 1958 RDI, // Class id register. |
| 1957 instance_call()->ArgumentCount(), | 1959 instance_call()->ArgumentCount(), |
| 1958 instance_call()->argument_names(), | 1960 instance_call()->argument_names(), |
| 1959 deopt, | 1961 deopt, |
| 1960 (is_smi_label == &handle_smi) ? &done : NULL, | 1962 (is_smi_label == &handle_smi) ? &done : NULL, |
| 1961 instance_call()->deopt_id(), | 1963 instance_call()->deopt_id(), |
| 1962 instance_call()->token_pos(), | 1964 instance_call()->token_pos(), |
| 1963 instance_call()->try_index()); | 1965 instance_call()->try_index()); |
| 1964 if (is_smi_label == &handle_smi) { | 1966 if (is_smi_label == &handle_smi) { |
| 1965 __ Bind(&handle_smi); | 1967 __ Bind(&handle_smi); |
| 1966 ASSERT(ic_data()->GetReceiverClassIdAt(0) == kSmi); | 1968 ASSERT(ic_data()->GetReceiverClassIdAt(0) == kSmiCid); |
| 1967 const Function& target = Function::ZoneHandle(ic_data()->GetTargetAt(0)); | 1969 const Function& target = Function::ZoneHandle(ic_data()->GetTargetAt(0)); |
| 1968 compiler->GenerateStaticCall(instance_call()->deopt_id(), | 1970 compiler->GenerateStaticCall(instance_call()->deopt_id(), |
| 1969 instance_call()->token_pos(), | 1971 instance_call()->token_pos(), |
| 1970 instance_call()->try_index(), | 1972 instance_call()->try_index(), |
| 1971 target, | 1973 target, |
| 1972 instance_call()->ArgumentCount(), | 1974 instance_call()->ArgumentCount(), |
| 1973 instance_call()->argument_names()); | 1975 instance_call()->argument_names()); |
| 1974 } | 1976 } |
| 1975 __ Bind(&done); | 1977 __ Bind(&done); |
| 1976 } | 1978 } |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1991 if ((kind() == Token::kEQ_STRICT) || (kind() == Token::kNE_STRICT)) { | 1993 if ((kind() == Token::kEQ_STRICT) || (kind() == Token::kNE_STRICT)) { |
| 1992 const int kNumInputs = 2; | 1994 const int kNumInputs = 2; |
| 1993 const int kNumTemps = 0; | 1995 const int kNumTemps = 0; |
| 1994 LocationSummary* locs = | 1996 LocationSummary* locs = |
| 1995 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1997 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1996 locs->set_in(0, Location::RequiresRegister()); | 1998 locs->set_in(0, Location::RequiresRegister()); |
| 1997 locs->set_in(1, Location::RequiresRegister()); | 1999 locs->set_in(1, Location::RequiresRegister()); |
| 1998 return locs; | 2000 return locs; |
| 1999 } | 2001 } |
| 2000 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { | 2002 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { |
| 2001 if (ICDataWithBothClassIds(*ic_data(), kSmi) || | 2003 if (ICDataWithBothClassIds(*ic_data(), kSmiCid) || |
| 2002 ICDataWithBothClassIds(*ic_data(), kDouble)) { | 2004 ICDataWithBothClassIds(*ic_data(), kDoubleCid)) { |
| 2003 const intptr_t kNumInputs = 2; | 2005 const intptr_t kNumInputs = 2; |
| 2004 const intptr_t kNumTemps = 1; | 2006 const intptr_t kNumTemps = 1; |
| 2005 LocationSummary* summary = | 2007 LocationSummary* summary = |
| 2006 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2008 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 2007 summary->set_in(0, Location::RequiresRegister()); | 2009 summary->set_in(0, Location::RequiresRegister()); |
| 2008 summary->set_in(1, Location::RequiresRegister()); | 2010 summary->set_in(1, Location::RequiresRegister()); |
| 2009 summary->set_temp(0, Location::RequiresRegister()); | 2011 summary->set_temp(0, Location::RequiresRegister()); |
| 2010 return summary; | 2012 return summary; |
| 2011 } | 2013 } |
| 2012 if ((kind() == Token::kEQ) || (kind() == Token::kNE)) { | 2014 if ((kind() == Token::kEQ) || (kind() == Token::kNE)) { |
| (...skipping 17 matching lines...) Expand all Loading... |
| 2030 if ((kind() == Token::kEQ_STRICT) || (kind() == Token::kNE_STRICT)) { | 2032 if ((kind() == Token::kEQ_STRICT) || (kind() == Token::kNE_STRICT)) { |
| 2031 Register left = locs()->in(0).reg(); | 2033 Register left = locs()->in(0).reg(); |
| 2032 Register right = locs()->in(1).reg(); | 2034 Register right = locs()->in(1).reg(); |
| 2033 __ cmpq(left, right); | 2035 __ cmpq(left, right); |
| 2034 Condition cond = (kind() == Token::kEQ_STRICT) ? EQUAL : NOT_EQUAL; | 2036 Condition cond = (kind() == Token::kEQ_STRICT) ? EQUAL : NOT_EQUAL; |
| 2035 EmitBranchOnCondition(compiler, cond); | 2037 EmitBranchOnCondition(compiler, cond); |
| 2036 return; | 2038 return; |
| 2037 } | 2039 } |
| 2038 // Relational or equality. | 2040 // Relational or equality. |
| 2039 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { | 2041 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { |
| 2040 if (ICDataWithBothClassIds(*ic_data(), kSmi)) { | 2042 if (ICDataWithBothClassIds(*ic_data(), kSmiCid)) { |
| 2041 EmitSmiComparisonOp(compiler, *locs(), kind(), this, | 2043 EmitSmiComparisonOp(compiler, *locs(), kind(), this, |
| 2042 deopt_id(), token_pos(), try_index()); | 2044 deopt_id(), token_pos(), try_index()); |
| 2043 return; | 2045 return; |
| 2044 } | 2046 } |
| 2045 if (ICDataWithBothClassIds(*ic_data(), kDouble)) { | 2047 if (ICDataWithBothClassIds(*ic_data(), kDoubleCid)) { |
| 2046 EmitDoubleComparisonOp(compiler, *locs(), kind(), this, | 2048 EmitDoubleComparisonOp(compiler, *locs(), kind(), this, |
| 2047 deopt_id(), token_pos(), try_index()); | 2049 deopt_id(), token_pos(), try_index()); |
| 2048 return; | 2050 return; |
| 2049 } | 2051 } |
| 2050 // TODO(srdjan): Add Smi/Double, Double/Smi comparisons. | 2052 // TODO(srdjan): Add Smi/Double, Double/Smi comparisons. |
| 2051 if ((kind() == Token::kEQ) || (kind() == Token::kNE)) { | 2053 if ((kind() == Token::kEQ) || (kind() == Token::kNE)) { |
| 2052 EmitGenericEqualityCompare(compiler, *locs(), kind(), this, *ic_data(), | 2054 EmitGenericEqualityCompare(compiler, *locs(), kind(), this, *ic_data(), |
| 2053 deopt_id(), token_pos(), try_index()); | 2055 deopt_id(), token_pos(), try_index()); |
| 2054 return; | 2056 return; |
| 2055 } | 2057 } |
| (...skipping 20 matching lines...) Expand all Loading... |
| 2076 ASSERT(locs()->out().reg() == RAX); | 2078 ASSERT(locs()->out().reg() == RAX); |
| 2077 __ CompareObject(locs()->out().reg(), compiler->bool_true()); | 2079 __ CompareObject(locs()->out().reg(), compiler->bool_true()); |
| 2078 EmitBranchOnCondition(compiler, branch_condition); | 2080 EmitBranchOnCondition(compiler, branch_condition); |
| 2079 } | 2081 } |
| 2080 | 2082 |
| 2081 } // namespace dart | 2083 } // namespace dart |
| 2082 | 2084 |
| 2083 #undef __ | 2085 #undef __ |
| 2084 | 2086 |
| 2085 #endif // defined TARGET_ARCH_X64 | 2087 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |