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 |