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

Side by Side Diff: runtime/vm/flow_graph_compiler_mips.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_ia32.cc ('k') | runtime/vm/flow_graph_compiler_x64.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_MIPS. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_MIPS.
6 #if defined(TARGET_ARCH_MIPS) 6 #if defined(TARGET_ARCH_MIPS)
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 432 matching lines...) Expand 10 before | Expand all | Expand 10 after
443 RawSubtypeTestCache* FlowGraphCompiler::GenerateUninstantiatedTypeTest( 443 RawSubtypeTestCache* FlowGraphCompiler::GenerateUninstantiatedTypeTest(
444 intptr_t token_pos, 444 intptr_t token_pos,
445 const AbstractType& type, 445 const AbstractType& type,
446 Label* is_instance_lbl, 446 Label* is_instance_lbl,
447 Label* is_not_instance_lbl) { 447 Label* is_not_instance_lbl) {
448 __ Comment("UninstantiatedTypeTest"); 448 __ Comment("UninstantiatedTypeTest");
449 ASSERT(!type.IsInstantiated()); 449 ASSERT(!type.IsInstantiated());
450 // Skip check if destination is a dynamic type. 450 // Skip check if destination is a dynamic type.
451 if (type.IsTypeParameter()) { 451 if (type.IsTypeParameter()) {
452 const TypeParameter& type_param = TypeParameter::Cast(type); 452 const TypeParameter& type_param = TypeParameter::Cast(type);
453 // Load instantiator (or null) and instantiator type arguments on stack. 453 // Load instantiator type arguments on stack.
454 __ lw(A1, Address(SP, 0)); // Get instantiator type arguments. 454 __ lw(A1, Address(SP, 0)); // Get instantiator type arguments.
455 // A1: instantiator type arguments. 455 // A1: instantiator type arguments.
456 // Check if type arguments are null, i.e. equivalent to vector of dynamic. 456 // Check if type arguments are null, i.e. equivalent to vector of dynamic.
457 __ LoadObject(T7, Object::null_object()); 457 __ LoadObject(T7, Object::null_object());
458 __ beq(A1, T7, is_instance_lbl); 458 __ beq(A1, T7, is_instance_lbl);
459 __ lw(T2, 459 __ lw(T2,
460 FieldAddress(A1, TypeArguments::type_at_offset(type_param.index()))); 460 FieldAddress(A1, TypeArguments::type_at_offset(type_param.index())));
461 // R2: concrete type of type. 461 // R2: concrete type of type.
462 // Check if type argument is dynamic. 462 // Check if type argument is dynamic.
463 __ BranchEqual(T2, 463 __ BranchEqual(T2,
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
568 568
569 569
570 // If instanceof type test cannot be performed successfully at compile time and 570 // If instanceof type test cannot be performed successfully at compile time and
571 // therefore eliminated, optimize it by adding inlined tests for: 571 // therefore eliminated, optimize it by adding inlined tests for:
572 // - NULL -> return false. 572 // - NULL -> return false.
573 // - Smi -> compile time subtype check (only if dst class is not parameterized). 573 // - Smi -> compile time subtype check (only if dst class is not parameterized).
574 // - Class equality (only if class is not parameterized). 574 // - Class equality (only if class is not parameterized).
575 // Inputs: 575 // Inputs:
576 // - A0: object. 576 // - A0: object.
577 // - A1: instantiator type arguments or raw_null. 577 // - A1: instantiator type arguments or raw_null.
578 // - A2: instantiator or raw_null.
579 // Returns: 578 // Returns:
580 // - true or false in V0. 579 // - true or false in V0.
581 void FlowGraphCompiler::GenerateInstanceOf(intptr_t token_pos, 580 void FlowGraphCompiler::GenerateInstanceOf(intptr_t token_pos,
582 intptr_t deopt_id, 581 intptr_t deopt_id,
583 const AbstractType& type, 582 const AbstractType& type,
584 bool negate_result, 583 bool negate_result,
585 LocationSummary* locs) { 584 LocationSummary* locs) {
586 ASSERT(type.IsFinalized() && !type.IsMalformed() && !type.IsMalbounded()); 585 ASSERT(type.IsFinalized() && !type.IsMalformed() && !type.IsMalbounded());
587 586
588 // Preserve instantiator (A2) and its type arguments (A1). 587 // Preserve instantiator type arguments (A1).
589 __ addiu(SP, SP, Immediate(-2 * kWordSize)); 588 __ addiu(SP, SP, Immediate(-1 * kWordSize));
590 __ sw(A2, Address(SP, 1 * kWordSize));
591 __ sw(A1, Address(SP, 0 * kWordSize)); 589 __ sw(A1, Address(SP, 0 * kWordSize));
592 590
593 Label is_instance, is_not_instance; 591 Label is_instance, is_not_instance;
594 // If type is instantiated and non-parameterized, we can inline code 592 // If type is instantiated and non-parameterized, we can inline code
595 // checking whether the tested instance is a Smi. 593 // checking whether the tested instance is a Smi.
596 if (type.IsInstantiated()) { 594 if (type.IsInstantiated()) {
597 // A null object is only an instance of Object and dynamic, which has 595 // A null object is only an instance of Object and dynamic, which has
598 // already been checked above (if the type is instantiated). So we can 596 // already been checked above (if the type is instantiated). So we can
599 // return false here if the instance is null (and if the type is 597 // return false here if the instance is null (and if the type is
600 // instantiated). 598 // instantiated).
601 // We can only inline this null check if the type is instantiated at compile 599 // We can only inline this null check if the type is instantiated at compile
602 // time, since an uninstantiated type at compile time could be Object or 600 // time, since an uninstantiated type at compile time could be Object or
603 // dynamic at run time. 601 // dynamic at run time.
604 __ BranchEqual(A0, Object::null_object(), 602 __ BranchEqual(A0, Object::null_object(),
605 type.IsNullType() ? &is_instance : &is_not_instance); 603 type.IsNullType() ? &is_instance : &is_not_instance);
606 } 604 }
607 605
608 // Generate inline instanceof test. 606 // Generate inline instanceof test.
609 SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle(zone()); 607 SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle(zone());
610 test_cache = GenerateInlineInstanceof(token_pos, type, 608 test_cache = GenerateInlineInstanceof(token_pos, type,
611 &is_instance, &is_not_instance); 609 &is_instance, &is_not_instance);
612 610
613 // test_cache is null if there is no fall-through. 611 // test_cache is null if there is no fall-through.
614 Label done; 612 Label done;
615 if (!test_cache.IsNull()) { 613 if (!test_cache.IsNull()) {
616 // Generate runtime call. 614 // Generate runtime call.
617 // Load instantiator (A2) and its type arguments (A1). 615 // Load instantiator type arguments (A1).
618 __ lw(A1, Address(SP, 0 * kWordSize)); 616 __ lw(A1, Address(SP, 0 * kWordSize));
619 __ lw(A2, Address(SP, 1 * kWordSize));
620 617
621 __ addiu(SP, SP, Immediate(-6 * kWordSize)); 618 __ addiu(SP, SP, Immediate(-5 * kWordSize));
622 __ LoadObject(TMP, Object::null_object()); 619 __ LoadObject(TMP, Object::null_object());
623 __ sw(TMP, Address(SP, 5 * kWordSize)); // Make room for the result. 620 __ sw(TMP, Address(SP, 4 * kWordSize)); // Make room for the result.
624 __ sw(A0, Address(SP, 4 * kWordSize)); // Push the instance. 621 __ sw(A0, Address(SP, 3 * kWordSize)); // Push the instance.
625 __ LoadObject(TMP, type); 622 __ LoadObject(TMP, type);
626 __ sw(TMP, Address(SP, 3 * kWordSize)); // Push the type. 623 __ sw(TMP, Address(SP, 2 * kWordSize)); // Push the type.
627 __ sw(A2, Address(SP, 2 * kWordSize)); // Push instantiator.
628 __ sw(A1, Address(SP, 1 * kWordSize)); // Push type arguments. 624 __ sw(A1, Address(SP, 1 * kWordSize)); // Push type arguments.
629 __ LoadUniqueObject(A0, test_cache); 625 __ LoadUniqueObject(A0, test_cache);
630 __ sw(A0, Address(SP, 0 * kWordSize)); 626 __ sw(A0, Address(SP, 0 * kWordSize));
631 GenerateRuntimeCall(token_pos, deopt_id, kInstanceofRuntimeEntry, 5, locs); 627 GenerateRuntimeCall(token_pos, deopt_id, kInstanceofRuntimeEntry, 4, locs);
632 // Pop the parameters supplied to the runtime entry. The result of the 628 // Pop the parameters supplied to the runtime entry. The result of the
633 // instanceof runtime call will be left as the result of the operation. 629 // instanceof runtime call will be left as the result of the operation.
634 __ lw(T0, Address(SP, 5 * kWordSize)); 630 __ lw(T0, Address(SP, 4 * kWordSize));
635 __ addiu(SP, SP, Immediate(6 * kWordSize)); 631 __ addiu(SP, SP, Immediate(5 * kWordSize));
636 if (negate_result) { 632 if (negate_result) {
637 __ LoadObject(V0, Bool::True()); 633 __ LoadObject(V0, Bool::True());
638 __ bne(T0, V0, &done); 634 __ bne(T0, V0, &done);
639 __ LoadObject(V0, Bool::False()); 635 __ LoadObject(V0, Bool::False());
640 } else { 636 } else {
641 __ mov(V0, T0); 637 __ mov(V0, T0);
642 } 638 }
643 __ b(&done); 639 __ b(&done);
644 } 640 }
645 __ Bind(&is_not_instance); 641 __ Bind(&is_not_instance);
646 __ LoadObject(V0, Bool::Get(negate_result)); 642 __ LoadObject(V0, Bool::Get(negate_result));
647 __ b(&done); 643 __ b(&done);
648 644
649 __ Bind(&is_instance); 645 __ Bind(&is_instance);
650 __ LoadObject(V0, Bool::Get(!negate_result)); 646 __ LoadObject(V0, Bool::Get(!negate_result));
651 __ Bind(&done); 647 __ Bind(&done);
652 // Remove instantiator (A2) and its type arguments (A1). 648 // Remove instantiator type arguments (A1).
653 __ Drop(2); 649 __ Drop(1);
654 } 650 }
655 651
656 652
657 // Optimize assignable type check by adding inlined tests for: 653 // Optimize assignable type check by adding inlined tests for:
658 // - NULL -> return NULL. 654 // - NULL -> return NULL.
659 // - Smi -> compile time subtype check (only if dst class is not parameterized). 655 // - Smi -> compile time subtype check (only if dst class is not parameterized).
660 // - Class equality (only if class is not parameterized). 656 // - Class equality (only if class is not parameterized).
661 // Inputs: 657 // Inputs:
662 // - A0: instance being type checked. 658 // - A0: instance being type checked.
663 // - A1: instantiator type arguments or raw_null. 659 // - A1: instantiator type arguments or raw_null.
664 // - A2: instantiator or raw_null.
665 // Returns: 660 // Returns:
666 // - object in A0 for successful assignable check (or throws TypeError). 661 // - object in A0 for successful assignable check (or throws TypeError).
667 // Clobbers: T0, T1, T2 662 // Clobbers: T0, T1, T2
668 // Performance notes: positive checks must be quick, negative checks can be slow 663 // Performance notes: positive checks must be quick, negative checks can be slow
669 // as they throw an exception. 664 // as they throw an exception.
670 void FlowGraphCompiler::GenerateAssertAssignable(intptr_t token_pos, 665 void FlowGraphCompiler::GenerateAssertAssignable(intptr_t token_pos,
671 intptr_t deopt_id, 666 intptr_t deopt_id,
672 const AbstractType& dst_type, 667 const AbstractType& dst_type,
673 const String& dst_name, 668 const String& dst_name,
674 LocationSummary* locs) { 669 LocationSummary* locs) {
675 __ Comment("AssertAssignable"); 670 __ Comment("AssertAssignable");
676 ASSERT(token_pos >= 0); 671 ASSERT(token_pos >= 0);
677 ASSERT(!dst_type.IsNull()); 672 ASSERT(!dst_type.IsNull());
678 ASSERT(dst_type.IsFinalized()); 673 ASSERT(dst_type.IsFinalized());
679 // Assignable check is skipped in FlowGraphBuilder, not here. 674 // Assignable check is skipped in FlowGraphBuilder, not here.
680 ASSERT(dst_type.IsMalformedOrMalbounded() || 675 ASSERT(dst_type.IsMalformedOrMalbounded() ||
681 (!dst_type.IsDynamicType() && !dst_type.IsObjectType())); 676 (!dst_type.IsDynamicType() && !dst_type.IsObjectType()));
682 // Preserve instantiator and its type arguments. 677 // Preserve instantiator type arguments.
683 __ addiu(SP, SP, Immediate(-2 * kWordSize)); 678 __ addiu(SP, SP, Immediate(-1 * kWordSize));
684 __ sw(A2, Address(SP, 1 * kWordSize)); 679 __ sw(A1, Address(SP, 0 * kWordSize));
685 680
686 // A null object is always assignable and is returned as result. 681 // A null object is always assignable and is returned as result.
687 Label is_assignable, runtime_call; 682 Label is_assignable, runtime_call;
688 683
689 __ BranchEqual(A0, Object::null_object(), &is_assignable); 684 __ BranchEqual(A0, Object::null_object(), &is_assignable);
690 __ delay_slot()->sw(A1, Address(SP, 0 * kWordSize)); 685 __ delay_slot()->sw(A1, Address(SP, 0 * kWordSize));
691 686
692 // Generate throw new TypeError() if the type is malformed or malbounded. 687 // Generate throw new TypeError() if the type is malformed or malbounded.
693 if (dst_type.IsMalformedOrMalbounded()) { 688 if (dst_type.IsMalformedOrMalbounded()) {
694 __ addiu(SP, SP, Immediate(-4 * kWordSize)); 689 __ addiu(SP, SP, Immediate(-4 * kWordSize));
695 __ LoadObject(TMP, Object::null_object()); 690 __ LoadObject(TMP, Object::null_object());
696 __ sw(TMP, Address(SP, 3 * kWordSize)); // Make room for the result. 691 __ sw(TMP, Address(SP, 3 * kWordSize)); // Make room for the result.
697 __ sw(A0, Address(SP, 2 * kWordSize)); // Push the source object. 692 __ sw(A0, Address(SP, 2 * kWordSize)); // Push the source object.
698 __ LoadObject(TMP, dst_name); 693 __ LoadObject(TMP, dst_name);
699 __ sw(TMP, Address(SP, 1 * kWordSize)); // Push the destination name. 694 __ sw(TMP, Address(SP, 1 * kWordSize)); // Push the destination name.
700 __ LoadObject(TMP, dst_type); 695 __ LoadObject(TMP, dst_type);
701 __ sw(TMP, Address(SP, 0 * kWordSize)); // Push the destination type. 696 __ sw(TMP, Address(SP, 0 * kWordSize)); // Push the destination type.
702 697
703 GenerateRuntimeCall(token_pos, 698 GenerateRuntimeCall(token_pos,
704 deopt_id, 699 deopt_id,
705 kBadTypeErrorRuntimeEntry, 700 kBadTypeErrorRuntimeEntry,
706 3, 701 3,
707 locs); 702 locs);
708 // We should never return here. 703 // We should never return here.
709 __ break_(0); 704 __ break_(0);
710 705
711 __ Bind(&is_assignable); // For a null object. 706 __ Bind(&is_assignable); // For a null object.
712 // Restore instantiator and its type arguments. 707 // Restore instantiator type arguments.
713 __ lw(A1, Address(SP, 0 * kWordSize)); 708 __ lw(A1, Address(SP, 0 * kWordSize));
714 __ lw(A2, Address(SP, 1 * kWordSize)); 709 __ addiu(SP, SP, Immediate(1 * kWordSize));
715 __ addiu(SP, SP, Immediate(2 * kWordSize));
716 return; 710 return;
717 } 711 }
718 712
719 // Generate inline type check, linking to runtime call if not assignable. 713 // Generate inline type check, linking to runtime call if not assignable.
720 SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle(zone()); 714 SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle(zone());
721 test_cache = GenerateInlineInstanceof(token_pos, dst_type, 715 test_cache = GenerateInlineInstanceof(token_pos, dst_type,
722 &is_assignable, &runtime_call); 716 &is_assignable, &runtime_call);
723 717
724 __ Bind(&runtime_call); 718 __ Bind(&runtime_call);
725 // Load instantiator (A2) and its type arguments (A1). 719 // Load instantiator type arguments (A1).
726 __ lw(A1, Address(SP, 0 * kWordSize)); 720 __ lw(A1, Address(SP, 0 * kWordSize));
727 __ lw(A2, Address(SP, 1 * kWordSize));
728 721
729 __ addiu(SP, SP, Immediate(-7 * kWordSize)); 722 __ addiu(SP, SP, Immediate(-6 * kWordSize));
730 __ LoadObject(TMP, Object::null_object()); 723 __ LoadObject(TMP, Object::null_object());
731 __ sw(TMP, Address(SP, 6 * kWordSize)); // Make room for the result. 724 __ sw(TMP, Address(SP, 5 * kWordSize)); // Make room for the result.
732 __ sw(A0, Address(SP, 5 * kWordSize)); // Push the source object. 725 __ sw(A0, Address(SP, 4 * kWordSize)); // Push the source object.
733 __ LoadObject(TMP, dst_type); 726 __ LoadObject(TMP, dst_type);
734 __ sw(TMP, Address(SP, 4 * kWordSize)); // Push the type of the destination. 727 __ sw(TMP, Address(SP, 3 * kWordSize)); // Push the type of the destination.
735 __ sw(A2, Address(SP, 3 * kWordSize)); // Push instantiator.
736 __ sw(A1, Address(SP, 2 * kWordSize)); // Push type arguments. 728 __ sw(A1, Address(SP, 2 * kWordSize)); // Push type arguments.
737 __ LoadObject(TMP, dst_name); 729 __ LoadObject(TMP, dst_name);
738 __ sw(TMP, Address(SP, 1 * kWordSize)); // Push the name of the destination. 730 __ sw(TMP, Address(SP, 1 * kWordSize)); // Push the name of the destination.
739 __ LoadUniqueObject(T0, test_cache); 731 __ LoadUniqueObject(T0, test_cache);
740 __ sw(T0, Address(SP, 0 * kWordSize)); 732 __ sw(T0, Address(SP, 0 * kWordSize));
741 733
742 GenerateRuntimeCall(token_pos, deopt_id, kTypeCheckRuntimeEntry, 6, locs); 734 GenerateRuntimeCall(token_pos, deopt_id, kTypeCheckRuntimeEntry, 5, locs);
743 // Pop the parameters supplied to the runtime entry. The result of the 735 // Pop the parameters supplied to the runtime entry. The result of the
744 // type check runtime call is the checked value. 736 // type check runtime call is the checked value.
745 __ lw(A0, Address(SP, 6 * kWordSize)); 737 __ lw(A0, Address(SP, 5 * kWordSize));
746 __ addiu(SP, SP, Immediate(7 * kWordSize)); 738 __ addiu(SP, SP, Immediate(6 * kWordSize));
747 739
748 __ Bind(&is_assignable); 740 __ Bind(&is_assignable);
749 // Restore instantiator and its type arguments. 741 // Restore instantiator type arguments.
750 __ lw(A1, Address(SP, 0 * kWordSize)); 742 __ lw(A1, Address(SP, 0 * kWordSize));
751 __ lw(A2, Address(SP, 1 * kWordSize)); 743 __ addiu(SP, SP, Immediate(1 * kWordSize));
752 __ addiu(SP, SP, Immediate(2 * kWordSize));
753 } 744 }
754 745
755 746
756 void FlowGraphCompiler::EmitInstructionEpilogue(Instruction* instr) { 747 void FlowGraphCompiler::EmitInstructionEpilogue(Instruction* instr) {
757 if (is_optimizing()) return; 748 if (is_optimizing()) return;
758 Definition* defn = instr->AsDefinition(); 749 Definition* defn = instr->AsDefinition();
759 if ((defn != NULL) && defn->HasTemp()) { 750 if ((defn != NULL) && defn->HasTemp()) {
760 __ Push(defn->locs()->out(0).reg()); 751 __ Push(defn->locs()->out(0).reg());
761 } 752 }
762 } 753 }
(...skipping 1142 matching lines...) Expand 10 before | Expand all | Expand 10 after
1905 __ AddImmediate(SP, kDoubleSize); 1896 __ AddImmediate(SP, kDoubleSize);
1906 } 1897 }
1907 1898
1908 1899
1909 #undef __ 1900 #undef __
1910 1901
1911 1902
1912 } // namespace dart 1903 } // namespace dart
1913 1904
1914 #endif // defined TARGET_ARCH_MIPS 1905 #endif // defined TARGET_ARCH_MIPS
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_compiler_ia32.cc ('k') | runtime/vm/flow_graph_compiler_x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698