Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(80)

Side by Side Diff: runtime/vm/flow_graph_compiler_x64.cc

Issue 1533383003: Remove instantiator argument in generated code for type tests. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: fix typo Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « runtime/vm/flow_graph_compiler_mips.cc ('k') | runtime/vm/flow_graph_optimizer.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/flow_graph_compiler.h" 8 #include "vm/flow_graph_compiler.h"
9 9
10 #include "vm/ast_printer.h" 10 #include "vm/ast_printer.h"
(...skipping 445 matching lines...) Expand 10 before | Expand all | Expand 10 after
456 RawSubtypeTestCache* FlowGraphCompiler::GenerateUninstantiatedTypeTest( 456 RawSubtypeTestCache* FlowGraphCompiler::GenerateUninstantiatedTypeTest(
457 intptr_t token_pos, 457 intptr_t token_pos,
458 const AbstractType& type, 458 const AbstractType& type,
459 Label* is_instance_lbl, 459 Label* is_instance_lbl,
460 Label* is_not_instance_lbl) { 460 Label* is_not_instance_lbl) {
461 __ Comment("UninstantiatedTypeTest"); 461 __ Comment("UninstantiatedTypeTest");
462 ASSERT(!type.IsInstantiated()); 462 ASSERT(!type.IsInstantiated());
463 // Skip check if destination is a dynamic type. 463 // Skip check if destination is a dynamic type.
464 if (type.IsTypeParameter()) { 464 if (type.IsTypeParameter()) {
465 const TypeParameter& type_param = TypeParameter::Cast(type); 465 const TypeParameter& type_param = TypeParameter::Cast(type);
466 // Load instantiator (or null) and instantiator type arguments on stack. 466 // Load instantiator type arguments on stack.
467 __ movq(RDX, Address(RSP, 0)); // Get instantiator type arguments. 467 __ movq(RDX, Address(RSP, 0)); // Get instantiator type arguments.
468 // RDX: instantiator type arguments. 468 // RDX: instantiator type arguments.
469 // Check if type arguments are null, i.e. equivalent to vector of dynamic. 469 // Check if type arguments are null, i.e. equivalent to vector of dynamic.
470 __ CompareObject(RDX, Object::null_object()); 470 __ CompareObject(RDX, Object::null_object());
471 __ j(EQUAL, is_instance_lbl); 471 __ j(EQUAL, is_instance_lbl);
472 __ movq(RDI, 472 __ movq(RDI,
473 FieldAddress(RDX, TypeArguments::type_at_offset(type_param.index()))); 473 FieldAddress(RDX, TypeArguments::type_at_offset(type_param.index())));
474 // RDI: Concrete type of type. 474 // RDI: Concrete type of type.
475 // Check if type argument is dynamic. 475 // Check if type argument is dynamic.
476 __ CompareObject(RDI, Object::dynamic_type()); 476 __ CompareObject(RDI, Object::dynamic_type());
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
582 582
583 583
584 // If instanceof type test cannot be performed successfully at compile time and 584 // If instanceof type test cannot be performed successfully at compile time and
585 // therefore eliminated, optimize it by adding inlined tests for: 585 // therefore eliminated, optimize it by adding inlined tests for:
586 // - NULL -> return false. 586 // - NULL -> return false.
587 // - Smi -> compile time subtype check (only if dst class is not parameterized). 587 // - Smi -> compile time subtype check (only if dst class is not parameterized).
588 // - Class equality (only if class is not parameterized). 588 // - Class equality (only if class is not parameterized).
589 // Inputs: 589 // Inputs:
590 // - RAX: object. 590 // - RAX: object.
591 // - RDX: instantiator type arguments or raw_null. 591 // - RDX: instantiator type arguments or raw_null.
592 // - RCX: instantiator or raw_null. 592 // Clobbers RDX.
593 // Clobbers RCX and RDX.
594 // Returns: 593 // Returns:
595 // - true or false in RAX. 594 // - true or false in RAX.
596 void FlowGraphCompiler::GenerateInstanceOf(intptr_t token_pos, 595 void FlowGraphCompiler::GenerateInstanceOf(intptr_t token_pos,
597 intptr_t deopt_id, 596 intptr_t deopt_id,
598 const AbstractType& type, 597 const AbstractType& type,
599 bool negate_result, 598 bool negate_result,
600 LocationSummary* locs) { 599 LocationSummary* locs) {
601 ASSERT(type.IsFinalized() && !type.IsMalformedOrMalbounded()); 600 ASSERT(type.IsFinalized() && !type.IsMalformedOrMalbounded());
602 601
603 Label is_instance, is_not_instance; 602 Label is_instance, is_not_instance;
604 __ pushq(RCX); // Store instantiator on stack.
605 __ pushq(RDX); // Store instantiator type arguments. 603 __ pushq(RDX); // Store instantiator type arguments.
606 // If type is instantiated and non-parameterized, we can inline code 604 // If type is instantiated and non-parameterized, we can inline code
607 // checking whether the tested instance is a Smi. 605 // checking whether the tested instance is a Smi.
608 if (type.IsInstantiated()) { 606 if (type.IsInstantiated()) {
609 // A null object is only an instance of Object and dynamic, which has 607 // A null object is only an instance of Object and dynamic, which has
610 // already been checked above (if the type is instantiated). So we can 608 // already been checked above (if the type is instantiated). So we can
611 // return false here if the instance is null (and if the type is 609 // return false here if the instance is null (and if the type is
612 // instantiated). 610 // instantiated).
613 // We can only inline this null check if the type is instantiated at compile 611 // We can only inline this null check if the type is instantiated at compile
614 // time, since an uninstantiated type at compile time could be Object or 612 // time, since an uninstantiated type at compile time could be Object or
615 // dynamic at run time. 613 // dynamic at run time.
616 __ CompareObject(RAX, Object::null_object()); 614 __ CompareObject(RAX, Object::null_object());
617 __ j(EQUAL, type.IsNullType() ? &is_instance : &is_not_instance); 615 __ j(EQUAL, type.IsNullType() ? &is_instance : &is_not_instance);
618 } 616 }
619 617
620 // Generate inline instanceof test. 618 // Generate inline instanceof test.
621 SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle(zone()); 619 SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle(zone());
622 test_cache = GenerateInlineInstanceof(token_pos, type, 620 test_cache = GenerateInlineInstanceof(token_pos, type,
623 &is_instance, &is_not_instance); 621 &is_instance, &is_not_instance);
624 622
625 // test_cache is null if there is no fall-through. 623 // test_cache is null if there is no fall-through.
626 Label done; 624 Label done;
627 if (!test_cache.IsNull()) { 625 if (!test_cache.IsNull()) {
628 // Generate runtime call. 626 // Generate runtime call.
629 __ movq(RDX, Address(RSP, 0)); // Get instantiator type arguments. 627 __ movq(RDX, Address(RSP, 0)); // Get instantiator type arguments.
630 __ movq(RCX, Address(RSP, kWordSize)); // Get instantiator.
631 __ PushObject(Object::null_object()); // Make room for the result. 628 __ PushObject(Object::null_object()); // Make room for the result.
632 __ pushq(RAX); // Push the instance. 629 __ pushq(RAX); // Push the instance.
633 __ PushObject(type); // Push the type. 630 __ PushObject(type); // Push the type.
634 __ pushq(RCX); // TODO(srdjan): Pass instantiator instead of null.
635 __ pushq(RDX); // Instantiator type arguments. 631 __ pushq(RDX); // Instantiator type arguments.
636 __ LoadUniqueObject(RAX, test_cache); 632 __ LoadUniqueObject(RAX, test_cache);
637 __ pushq(RAX); 633 __ pushq(RAX);
638 GenerateRuntimeCall(token_pos, 634 GenerateRuntimeCall(token_pos,
639 deopt_id, 635 deopt_id,
640 kInstanceofRuntimeEntry, 636 kInstanceofRuntimeEntry,
641 5, 637 4,
642 locs); 638 locs);
643 // Pop the parameters supplied to the runtime entry. The result of the 639 // Pop the parameters supplied to the runtime entry. The result of the
644 // instanceof runtime call will be left as the result of the operation. 640 // instanceof runtime call will be left as the result of the operation.
645 __ Drop(5); 641 __ Drop(4);
646 if (negate_result) { 642 if (negate_result) {
647 __ popq(RDX); 643 __ popq(RDX);
648 __ LoadObject(RAX, Bool::True()); 644 __ LoadObject(RAX, Bool::True());
649 __ cmpq(RDX, RAX); 645 __ cmpq(RDX, RAX);
650 __ j(NOT_EQUAL, &done, Assembler::kNearJump); 646 __ j(NOT_EQUAL, &done, Assembler::kNearJump);
651 __ LoadObject(RAX, Bool::False()); 647 __ LoadObject(RAX, Bool::False());
652 } else { 648 } else {
653 __ popq(RAX); 649 __ popq(RAX);
654 } 650 }
655 __ jmp(&done, Assembler::kNearJump); 651 __ jmp(&done, Assembler::kNearJump);
656 } 652 }
657 __ Bind(&is_not_instance); 653 __ Bind(&is_not_instance);
658 __ LoadObject(RAX, Bool::Get(negate_result)); 654 __ LoadObject(RAX, Bool::Get(negate_result));
659 __ jmp(&done, Assembler::kNearJump); 655 __ jmp(&done, Assembler::kNearJump);
660 656
661 __ Bind(&is_instance); 657 __ Bind(&is_instance);
662 __ LoadObject(RAX, Bool::Get(!negate_result)); 658 __ LoadObject(RAX, Bool::Get(!negate_result));
663 __ Bind(&done); 659 __ Bind(&done);
664 __ popq(RDX); // Remove pushed instantiator type arguments. 660 __ popq(RDX); // Remove pushed instantiator type arguments.
665 __ popq(RCX); // Remove pushed instantiator.
666 } 661 }
667 662
668 663
669 // Optimize assignable type check by adding inlined tests for: 664 // Optimize assignable type check by adding inlined tests for:
670 // - NULL -> return NULL. 665 // - NULL -> return NULL.
671 // - Smi -> compile time subtype check (only if dst class is not parameterized). 666 // - Smi -> compile time subtype check (only if dst class is not parameterized).
672 // - Class equality (only if class is not parameterized). 667 // - Class equality (only if class is not parameterized).
673 // Inputs: 668 // Inputs:
674 // - RAX: object. 669 // - RAX: object.
675 // - RDX: instantiator type arguments or raw_null. 670 // - RDX: instantiator type arguments or raw_null.
676 // - RCX: instantiator or raw_null.
677 // Returns: 671 // Returns:
678 // - object in RAX for successful assignable check (or throws TypeError). 672 // - object in RAX for successful assignable check (or throws TypeError).
679 // Performance notes: positive checks must be quick, negative checks can be slow 673 // Performance notes: positive checks must be quick, negative checks can be slow
680 // as they throw an exception. 674 // as they throw an exception.
681 void FlowGraphCompiler::GenerateAssertAssignable(intptr_t token_pos, 675 void FlowGraphCompiler::GenerateAssertAssignable(intptr_t token_pos,
682 intptr_t deopt_id, 676 intptr_t deopt_id,
683 const AbstractType& dst_type, 677 const AbstractType& dst_type,
684 const String& dst_name, 678 const String& dst_name,
685 LocationSummary* locs) { 679 LocationSummary* locs) {
686 ASSERT(token_pos >= 0); 680 ASSERT(token_pos >= 0);
687 ASSERT(!dst_type.IsNull()); 681 ASSERT(!dst_type.IsNull());
688 ASSERT(dst_type.IsFinalized()); 682 ASSERT(dst_type.IsFinalized());
689 // Assignable check is skipped in FlowGraphBuilder, not here. 683 // Assignable check is skipped in FlowGraphBuilder, not here.
690 ASSERT(dst_type.IsMalformedOrMalbounded() || 684 ASSERT(dst_type.IsMalformedOrMalbounded() ||
691 (!dst_type.IsDynamicType() && !dst_type.IsObjectType())); 685 (!dst_type.IsDynamicType() && !dst_type.IsObjectType()));
692 __ pushq(RCX); // Store instantiator.
693 __ pushq(RDX); // Store instantiator type arguments. 686 __ pushq(RDX); // Store instantiator type arguments.
694 // A null object is always assignable and is returned as result. 687 // A null object is always assignable and is returned as result.
695 Label is_assignable, runtime_call; 688 Label is_assignable, runtime_call;
696 __ CompareObject(RAX, Object::null_object()); 689 __ CompareObject(RAX, Object::null_object());
697 __ j(EQUAL, &is_assignable); 690 __ j(EQUAL, &is_assignable);
698 691
699 // Generate throw new TypeError() if the type is malformed or malbounded. 692 // Generate throw new TypeError() if the type is malformed or malbounded.
700 if (dst_type.IsMalformedOrMalbounded()) { 693 if (dst_type.IsMalformedOrMalbounded()) {
701 __ PushObject(Object::null_object()); // Make room for the result. 694 __ PushObject(Object::null_object()); // Make room for the result.
702 __ pushq(RAX); // Push the source object. 695 __ pushq(RAX); // Push the source object.
703 __ PushObject(dst_name); // Push the name of the destination. 696 __ PushObject(dst_name); // Push the name of the destination.
704 __ PushObject(dst_type); // Push the type of the destination. 697 __ PushObject(dst_type); // Push the type of the destination.
705 GenerateRuntimeCall(token_pos, 698 GenerateRuntimeCall(token_pos,
706 deopt_id, 699 deopt_id,
707 kBadTypeErrorRuntimeEntry, 700 kBadTypeErrorRuntimeEntry,
708 3, 701 3,
709 locs); 702 locs);
710 // We should never return here. 703 // We should never return here.
711 __ int3(); 704 __ int3();
712 705
713 __ Bind(&is_assignable); // For a null object. 706 __ Bind(&is_assignable); // For a null object.
714 __ popq(RDX); // Remove pushed instantiator type arguments. 707 __ popq(RDX); // Remove pushed instantiator type arguments.
715 __ popq(RCX); // Remove pushed instantiator.
716 return; 708 return;
717 } 709 }
718 710
719 // Generate inline type check, linking to runtime call if not assignable. 711 // Generate inline type check, linking to runtime call if not assignable.
720 SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle(zone()); 712 SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle(zone());
721 test_cache = GenerateInlineInstanceof(token_pos, dst_type, 713 test_cache = GenerateInlineInstanceof(token_pos, dst_type,
722 &is_assignable, &runtime_call); 714 &is_assignable, &runtime_call);
723 715
724 __ Bind(&runtime_call); 716 __ Bind(&runtime_call);
725 __ movq(RDX, Address(RSP, 0)); // Get instantiator type arguments. 717 __ movq(RDX, Address(RSP, 0)); // Get instantiator type arguments.
726 __ movq(RCX, Address(RSP, kWordSize)); // Get instantiator.
727 __ PushObject(Object::null_object()); // Make room for the result. 718 __ PushObject(Object::null_object()); // Make room for the result.
728 __ pushq(RAX); // Push the source object. 719 __ pushq(RAX); // Push the source object.
729 __ PushObject(dst_type); // Push the type of the destination. 720 __ PushObject(dst_type); // Push the type of the destination.
730 __ pushq(RCX); // Instantiator.
731 __ pushq(RDX); // Instantiator type arguments. 721 __ pushq(RDX); // Instantiator type arguments.
732 __ PushObject(dst_name); // Push the name of the destination. 722 __ PushObject(dst_name); // Push the name of the destination.
733 __ LoadUniqueObject(RAX, test_cache); 723 __ LoadUniqueObject(RAX, test_cache);
734 __ pushq(RAX); 724 __ pushq(RAX);
735 GenerateRuntimeCall(token_pos, deopt_id, kTypeCheckRuntimeEntry, 6, locs); 725 GenerateRuntimeCall(token_pos, deopt_id, kTypeCheckRuntimeEntry, 5, locs);
736 // Pop the parameters supplied to the runtime entry. The result of the 726 // Pop the parameters supplied to the runtime entry. The result of the
737 // type check runtime call is the checked value. 727 // type check runtime call is the checked value.
738 __ Drop(6); 728 __ Drop(5);
739 __ popq(RAX); 729 __ popq(RAX);
740 730
741 __ Bind(&is_assignable); 731 __ Bind(&is_assignable);
742 __ popq(RDX); // Remove pushed instantiator type arguments. 732 __ popq(RDX); // Remove pushed instantiator type arguments.
743 __ popq(RCX); // Remove pushed instantiator.
744 } 733 }
745 734
746 735
747 void FlowGraphCompiler::EmitInstructionEpilogue(Instruction* instr) { 736 void FlowGraphCompiler::EmitInstructionEpilogue(Instruction* instr) {
748 if (is_optimizing()) { 737 if (is_optimizing()) {
749 return; 738 return;
750 } 739 }
751 Definition* defn = instr->AsDefinition(); 740 Definition* defn = instr->AsDefinition();
752 if ((defn != NULL) && defn->HasTemp()) { 741 if ((defn != NULL) && defn->HasTemp()) {
753 Location value = defn->locs()->out(0); 742 Location value = defn->locs()->out(0);
(...skipping 1067 matching lines...) Expand 10 before | Expand all | Expand 10 after
1821 __ movups(reg, Address(RSP, 0)); 1810 __ movups(reg, Address(RSP, 0));
1822 __ AddImmediate(RSP, Immediate(kFpuRegisterSize)); 1811 __ AddImmediate(RSP, Immediate(kFpuRegisterSize));
1823 } 1812 }
1824 1813
1825 1814
1826 #undef __ 1815 #undef __
1827 1816
1828 } // namespace dart 1817 } // namespace dart
1829 1818
1830 #endif // defined TARGET_ARCH_X64 1819 #endif // defined TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_compiler_mips.cc ('k') | runtime/vm/flow_graph_optimizer.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698