| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64. |
| 6 #if defined(TARGET_ARCH_X64) | 6 #if defined(TARGET_ARCH_X64) |
| 7 | 7 |
| 8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
| 9 | 9 |
| 10 #include "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
| (...skipping 435 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 446 const ICData& original_ic_data) { | 446 const ICData& original_ic_data) { |
| 447 if (!compiler->is_optimizing()) { | 447 if (!compiler->is_optimizing()) { |
| 448 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, | 448 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, |
| 449 deopt_id, | 449 deopt_id, |
| 450 token_pos); | 450 token_pos); |
| 451 } | 451 } |
| 452 const int kNumberOfArguments = 2; | 452 const int kNumberOfArguments = 2; |
| 453 const Array& kNoArgumentNames = Object::null_array(); | 453 const Array& kNoArgumentNames = Object::null_array(); |
| 454 const int kNumArgumentsChecked = 2; | 454 const int kNumArgumentsChecked = 2; |
| 455 | 455 |
| 456 Label check_identity; | |
| 457 __ LoadObject(TMP, Object::null_object(), PP); | |
| 458 __ cmpq(Address(RSP, 0 * kWordSize), TMP); | |
| 459 __ j(EQUAL, &check_identity); | |
| 460 __ cmpq(Address(RSP, 1 * kWordSize), TMP); | |
| 461 __ j(EQUAL, &check_identity); | |
| 462 | |
| 463 ICData& equality_ic_data = ICData::ZoneHandle(original_ic_data.raw()); | 456 ICData& equality_ic_data = ICData::ZoneHandle(original_ic_data.raw()); |
| 464 if (compiler->is_optimizing() && FLAG_propagate_ic_data) { | 457 if (compiler->is_optimizing() && FLAG_propagate_ic_data) { |
| 465 ASSERT(!original_ic_data.IsNull()); | 458 ASSERT(!original_ic_data.IsNull()); |
| 466 if (original_ic_data.NumberOfChecks() == 0) { | 459 if (original_ic_data.NumberOfChecks() == 0) { |
| 467 // IC call for reoptimization populates original ICData. | 460 // IC call for reoptimization populates original ICData. |
| 468 equality_ic_data = original_ic_data.raw(); | 461 equality_ic_data = original_ic_data.raw(); |
| 469 } else { | 462 } else { |
| 470 // Megamorphic call. | 463 // Megamorphic call. |
| 471 equality_ic_data = original_ic_data.AsUnaryClassChecks(); | 464 equality_ic_data = original_ic_data.AsUnaryClassChecks(); |
| 472 } | 465 } |
| 473 } else { | 466 } else { |
| 474 const Array& arguments_descriptor = | 467 const Array& arguments_descriptor = |
| 475 Array::Handle(ArgumentsDescriptor::New(kNumberOfArguments, | 468 Array::Handle(ArgumentsDescriptor::New(kNumberOfArguments, |
| 476 kNoArgumentNames)); | 469 kNoArgumentNames)); |
| 477 equality_ic_data = ICData::New(compiler->parsed_function().function(), | 470 equality_ic_data = ICData::New(compiler->parsed_function().function(), |
| 478 Symbols::EqualOperator(), | 471 Symbols::EqualOperator(), |
| 479 arguments_descriptor, | 472 arguments_descriptor, |
| 480 deopt_id, | 473 deopt_id, |
| 481 kNumArgumentsChecked); | 474 kNumArgumentsChecked); |
| 482 } | 475 } |
| 483 compiler->GenerateInstanceCall(deopt_id, | 476 compiler->GenerateInstanceCall(deopt_id, |
| 484 token_pos, | 477 token_pos, |
| 485 kNumberOfArguments, | 478 kNumberOfArguments, |
| 486 kNoArgumentNames, | 479 kNoArgumentNames, |
| 487 locs, | 480 locs, |
| 488 equality_ic_data); | 481 equality_ic_data); |
| 489 Label check_ne; | |
| 490 __ jmp(&check_ne); | |
| 491 | |
| 492 __ Bind(&check_identity); | |
| 493 Label equality_done; | |
| 494 if (compiler->is_optimizing()) { | |
| 495 // No need to update IC data. | |
| 496 Label is_true; | |
| 497 __ popq(RAX); | |
| 498 __ popq(RDX); | |
| 499 __ cmpq(RAX, RDX); | |
| 500 __ j(EQUAL, &is_true); | |
| 501 __ LoadObject(RAX, Bool::Get(kind != Token::kEQ), PP); | |
| 502 __ jmp(&equality_done); | |
| 503 __ Bind(&is_true); | |
| 504 __ LoadObject(RAX, Bool::Get(kind == Token::kEQ), PP); | |
| 505 if (kind == Token::kNE) { | |
| 506 // Skip not-equal result conversion. | |
| 507 __ jmp(&equality_done); | |
| 508 } | |
| 509 } else { | |
| 510 // Call stub, load IC data in register. The stub will update ICData if | |
| 511 // necessary. | |
| 512 Register ic_data_reg = locs->temp(0).reg(); | |
| 513 ASSERT(ic_data_reg == RBX); // Stub depends on it. | |
| 514 __ LoadObject(ic_data_reg, equality_ic_data, PP); | |
| 515 compiler->GenerateCall(token_pos, | |
| 516 &StubCode::EqualityWithNullArgLabel(), | |
| 517 PcDescriptors::kRuntimeCall, | |
| 518 locs); | |
| 519 __ Drop(2); | |
| 520 } | |
| 521 __ Bind(&check_ne); | |
| 522 if (kind == Token::kNE) { | 482 if (kind == Token::kNE) { |
| 523 Label true_label, done; | 483 Label true_label, done; |
| 524 // Negate the condition: true label returns false and vice versa. | 484 // Negate the condition: true label returns false and vice versa. |
| 525 __ CompareObject(RAX, Bool::True(), PP); | 485 __ CompareObject(RAX, Bool::True(), PP); |
| 526 __ j(EQUAL, &true_label, Assembler::kNearJump); | 486 __ j(EQUAL, &true_label, Assembler::kNearJump); |
| 527 __ LoadObject(RAX, Bool::True(), PP); | 487 __ LoadObject(RAX, Bool::True(), PP); |
| 528 __ jmp(&done, Assembler::kNearJump); | 488 __ jmp(&done, Assembler::kNearJump); |
| 529 __ Bind(&true_label); | 489 __ Bind(&true_label); |
| 530 __ LoadObject(RAX, Bool::False(), PP); | 490 __ LoadObject(RAX, Bool::False(), PP); |
| 531 __ Bind(&done); | 491 __ Bind(&done); |
| 532 } | 492 } |
| 533 __ Bind(&equality_done); | |
| 534 } | 493 } |
| 535 | 494 |
| 536 | 495 |
| 537 static void LoadValueCid(FlowGraphCompiler* compiler, | 496 static void LoadValueCid(FlowGraphCompiler* compiler, |
| 538 Register value_cid_reg, | 497 Register value_cid_reg, |
| 539 Register value_reg, | 498 Register value_reg, |
| 540 Label* value_is_smi = NULL) { | 499 Label* value_is_smi = NULL) { |
| 541 Label done; | 500 Label done; |
| 542 if (value_is_smi == NULL) { | 501 if (value_is_smi == NULL) { |
| 543 __ LoadImmediate(value_cid_reg, Immediate(kSmiCid), PP); | 502 __ LoadImmediate(value_cid_reg, Immediate(kSmiCid), PP); |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 697 LocationSummary* locs, | 656 LocationSummary* locs, |
| 698 Token::Kind kind, | 657 Token::Kind kind, |
| 699 BranchInstr* branch, | 658 BranchInstr* branch, |
| 700 const ICData& ic_data, | 659 const ICData& ic_data, |
| 701 intptr_t deopt_id, | 660 intptr_t deopt_id, |
| 702 intptr_t token_pos) { | 661 intptr_t token_pos) { |
| 703 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); | 662 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); |
| 704 ASSERT(!ic_data.IsNull() && (ic_data.NumberOfChecks() > 0)); | 663 ASSERT(!ic_data.IsNull() && (ic_data.NumberOfChecks() > 0)); |
| 705 Register left = locs->in(0).reg(); | 664 Register left = locs->in(0).reg(); |
| 706 Register right = locs->in(1).reg(); | 665 Register right = locs->in(1).reg(); |
| 707 | |
| 708 Label done, identity_compare, non_null_compare; | |
| 709 __ CompareObject(right, Object::null_object(), PP); | |
| 710 __ j(EQUAL, &identity_compare, Assembler::kNearJump); | |
| 711 __ CompareObject(left, Object::null_object(), PP); | |
| 712 __ j(NOT_EQUAL, &non_null_compare, Assembler::kNearJump); | |
| 713 // Comparison with NULL is "===". | |
| 714 __ Bind(&identity_compare); | |
| 715 __ cmpq(left, right); | |
| 716 Condition cond = TokenKindToSmiCondition(kind); | |
| 717 if (branch != NULL) { | |
| 718 branch->EmitBranchOnCondition(compiler, cond); | |
| 719 } else { | |
| 720 Register result = locs->out().reg(); | |
| 721 Label load_true; | |
| 722 __ j(cond, &load_true, Assembler::kNearJump); | |
| 723 __ LoadObject(result, Bool::False(), PP); | |
| 724 __ jmp(&done); | |
| 725 __ Bind(&load_true); | |
| 726 __ LoadObject(result, Bool::True(), PP); | |
| 727 } | |
| 728 __ jmp(&done); | |
| 729 __ Bind(&non_null_compare); // Receiver is not null. | |
| 730 __ pushq(left); | 666 __ pushq(left); |
| 731 __ pushq(right); | 667 __ pushq(right); |
| 732 EmitEqualityAsPolymorphicCall(compiler, ic_data, locs, branch, kind, | 668 EmitEqualityAsPolymorphicCall(compiler, ic_data, locs, branch, kind, |
| 733 deopt_id, token_pos); | 669 deopt_id, token_pos); |
| 734 __ Bind(&done); | |
| 735 } | 670 } |
| 736 | 671 |
| 737 | 672 |
| 738 static Condition FlipCondition(Condition condition) { | 673 static Condition FlipCondition(Condition condition) { |
| 739 switch (condition) { | 674 switch (condition) { |
| 740 case EQUAL: return EQUAL; | 675 case EQUAL: return EQUAL; |
| 741 case NOT_EQUAL: return NOT_EQUAL; | 676 case NOT_EQUAL: return NOT_EQUAL; |
| 742 case LESS: return GREATER; | 677 case LESS: return GREATER; |
| 743 case LESS_EQUAL: return GREATER_EQUAL; | 678 case LESS_EQUAL: return GREATER_EQUAL; |
| 744 case GREATER: return LESS; | 679 case GREATER: return LESS; |
| (...skipping 4115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4860 PcDescriptors::kOther, | 4795 PcDescriptors::kOther, |
| 4861 locs()); | 4796 locs()); |
| 4862 __ Drop(2); // Discard type arguments and receiver. | 4797 __ Drop(2); // Discard type arguments and receiver. |
| 4863 } | 4798 } |
| 4864 | 4799 |
| 4865 } // namespace dart | 4800 } // namespace dart |
| 4866 | 4801 |
| 4867 #undef __ | 4802 #undef __ |
| 4868 | 4803 |
| 4869 #endif // defined TARGET_ARCH_X64 | 4804 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |