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

Side by Side Diff: runtime/vm/flow_graph_compiler_ia32.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_arm64.cc ('k') | runtime/vm/flow_graph_compiler_mips.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_IA32. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32.
6 #if defined(TARGET_ARCH_IA32) 6 #if defined(TARGET_ARCH_IA32)
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 452 matching lines...) Expand 10 before | Expand all | Expand 10 after
463 const AbstractType& type, 463 const AbstractType& type,
464 Label* is_instance_lbl, 464 Label* is_instance_lbl,
465 Label* is_not_instance_lbl) { 465 Label* is_not_instance_lbl) {
466 __ Comment("UninstantiatedTypeTest"); 466 __ Comment("UninstantiatedTypeTest");
467 ASSERT(!type.IsInstantiated()); 467 ASSERT(!type.IsInstantiated());
468 // Skip check if destination is a dynamic type. 468 // Skip check if destination is a dynamic type.
469 const Immediate& raw_null = 469 const Immediate& raw_null =
470 Immediate(reinterpret_cast<intptr_t>(Object::null())); 470 Immediate(reinterpret_cast<intptr_t>(Object::null()));
471 if (type.IsTypeParameter()) { 471 if (type.IsTypeParameter()) {
472 const TypeParameter& type_param = TypeParameter::Cast(type); 472 const TypeParameter& type_param = TypeParameter::Cast(type);
473 // Load instantiator (or null) and instantiator type arguments on stack. 473 // Load instantiator type arguments on stack.
474 __ movl(EDX, Address(ESP, 0)); // Get instantiator type arguments. 474 __ movl(EDX, Address(ESP, 0)); // Get instantiator type arguments.
475 // EDX: instantiator type arguments. 475 // EDX: instantiator type arguments.
476 // Check if type arguments are null, i.e. equivalent to vector of dynamic. 476 // Check if type arguments are null, i.e. equivalent to vector of dynamic.
477 __ cmpl(EDX, raw_null); 477 __ cmpl(EDX, raw_null);
478 __ j(EQUAL, is_instance_lbl); 478 __ j(EQUAL, is_instance_lbl);
479 __ movl(EDI, 479 __ movl(EDI,
480 FieldAddress(EDX, TypeArguments::type_at_offset(type_param.index()))); 480 FieldAddress(EDX, TypeArguments::type_at_offset(type_param.index())));
481 // EDI: concrete type of type. 481 // EDI: concrete type of type.
482 // Check if type argument is dynamic. 482 // Check if type argument is dynamic.
483 __ CompareObject(EDI, Object::dynamic_type()); 483 __ CompareObject(EDI, Object::dynamic_type());
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
588 588
589 589
590 // If instanceof type test cannot be performed successfully at compile time and 590 // If instanceof type test cannot be performed successfully at compile time and
591 // therefore eliminated, optimize it by adding inlined tests for: 591 // therefore eliminated, optimize it by adding inlined tests for:
592 // - NULL -> return false. 592 // - NULL -> return false.
593 // - Smi -> compile time subtype check (only if dst class is not parameterized). 593 // - Smi -> compile time subtype check (only if dst class is not parameterized).
594 // - Class equality (only if class is not parameterized). 594 // - Class equality (only if class is not parameterized).
595 // Inputs: 595 // Inputs:
596 // - EAX: object. 596 // - EAX: object.
597 // - EDX: instantiator type arguments or raw_null. 597 // - EDX: instantiator type arguments or raw_null.
598 // - ECX: instantiator or raw_null. 598 // Clobbers EDX.
599 // Clobbers ECX and EDX.
600 // Returns: 599 // Returns:
601 // - true or false in EAX. 600 // - true or false in EAX.
602 void FlowGraphCompiler::GenerateInstanceOf(intptr_t token_pos, 601 void FlowGraphCompiler::GenerateInstanceOf(intptr_t token_pos,
603 intptr_t deopt_id, 602 intptr_t deopt_id,
604 const AbstractType& type, 603 const AbstractType& type,
605 bool negate_result, 604 bool negate_result,
606 LocationSummary* locs) { 605 LocationSummary* locs) {
607 ASSERT(type.IsFinalized() && !type.IsMalformedOrMalbounded()); 606 ASSERT(type.IsFinalized() && !type.IsMalformedOrMalbounded());
608 607
609 const Immediate& raw_null = 608 const Immediate& raw_null =
610 Immediate(reinterpret_cast<intptr_t>(Object::null())); 609 Immediate(reinterpret_cast<intptr_t>(Object::null()));
611 Label is_instance, is_not_instance; 610 Label is_instance, is_not_instance;
612 __ pushl(ECX); // Store instantiator on stack.
613 __ pushl(EDX); // Store instantiator type arguments. 611 __ pushl(EDX); // Store instantiator type arguments.
614 // If type is instantiated and non-parameterized, we can inline code 612 // If type is instantiated and non-parameterized, we can inline code
615 // checking whether the tested instance is a Smi. 613 // checking whether the tested instance is a Smi.
616 if (type.IsInstantiated()) { 614 if (type.IsInstantiated()) {
617 // A null object is only an instance of Object and dynamic, which has 615 // A null object is only an instance of Object and dynamic, which has
618 // already been checked above (if the type is instantiated). So we can 616 // already been checked above (if the type is instantiated). So we can
619 // return false here if the instance is null (and if the type is 617 // return false here if the instance is null (and if the type is
620 // instantiated). 618 // instantiated).
621 // We can only inline this null check if the type is instantiated at compile 619 // We can only inline this null check if the type is instantiated at compile
622 // time, since an uninstantiated type at compile time could be Object or 620 // time, since an uninstantiated type at compile time could be Object or
623 // dynamic at run time. 621 // dynamic at run time.
624 __ cmpl(EAX, raw_null); 622 __ cmpl(EAX, raw_null);
625 __ j(EQUAL, type.IsNullType() ? &is_instance : &is_not_instance); 623 __ j(EQUAL, type.IsNullType() ? &is_instance : &is_not_instance);
626 } 624 }
627 625
628 // Generate inline instanceof test. 626 // Generate inline instanceof test.
629 SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle(zone()); 627 SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle(zone());
630 test_cache = GenerateInlineInstanceof(token_pos, type, 628 test_cache = GenerateInlineInstanceof(token_pos, type,
631 &is_instance, &is_not_instance); 629 &is_instance, &is_not_instance);
632 630
633 // test_cache is null if there is no fall-through. 631 // test_cache is null if there is no fall-through.
634 Label done; 632 Label done;
635 if (!test_cache.IsNull()) { 633 if (!test_cache.IsNull()) {
636 // Generate runtime call. 634 // Generate runtime call.
637 __ movl(EDX, Address(ESP, 0)); // Get instantiator type arguments. 635 __ movl(EDX, Address(ESP, 0)); // Get instantiator type arguments.
638 __ movl(ECX, Address(ESP, kWordSize)); // Get instantiator.
639 __ PushObject(Object::null_object()); // Make room for the result. 636 __ PushObject(Object::null_object()); // Make room for the result.
640 __ pushl(EAX); // Push the instance. 637 __ pushl(EAX); // Push the instance.
641 __ PushObject(type); // Push the type. 638 __ PushObject(type); // Push the type.
642 __ pushl(ECX); // Instantiator.
643 __ pushl(EDX); // Instantiator type arguments. 639 __ pushl(EDX); // Instantiator type arguments.
644 __ LoadObject(EAX, test_cache); 640 __ LoadObject(EAX, test_cache);
645 __ pushl(EAX); 641 __ pushl(EAX);
646 GenerateRuntimeCall(token_pos, 642 GenerateRuntimeCall(token_pos,
647 deopt_id, 643 deopt_id,
648 kInstanceofRuntimeEntry, 644 kInstanceofRuntimeEntry,
649 5, 645 4,
650 locs); 646 locs);
651 // Pop the parameters supplied to the runtime entry. The result of the 647 // Pop the parameters supplied to the runtime entry. The result of the
652 // instanceof runtime call will be left as the result of the operation. 648 // instanceof runtime call will be left as the result of the operation.
653 __ Drop(5); 649 __ Drop(4);
654 if (negate_result) { 650 if (negate_result) {
655 __ popl(EDX); 651 __ popl(EDX);
656 __ LoadObject(EAX, Bool::True()); 652 __ LoadObject(EAX, Bool::True());
657 __ cmpl(EDX, EAX); 653 __ cmpl(EDX, EAX);
658 __ j(NOT_EQUAL, &done, Assembler::kNearJump); 654 __ j(NOT_EQUAL, &done, Assembler::kNearJump);
659 __ LoadObject(EAX, Bool::False()); 655 __ LoadObject(EAX, Bool::False());
660 } else { 656 } else {
661 __ popl(EAX); 657 __ popl(EAX);
662 } 658 }
663 __ jmp(&done, Assembler::kNearJump); 659 __ jmp(&done, Assembler::kNearJump);
664 } 660 }
665 __ Bind(&is_not_instance); 661 __ Bind(&is_not_instance);
666 __ LoadObject(EAX, Bool::Get(negate_result)); 662 __ LoadObject(EAX, Bool::Get(negate_result));
667 __ jmp(&done, Assembler::kNearJump); 663 __ jmp(&done, Assembler::kNearJump);
668 664
669 __ Bind(&is_instance); 665 __ Bind(&is_instance);
670 __ LoadObject(EAX, Bool::Get(!negate_result)); 666 __ LoadObject(EAX, Bool::Get(!negate_result));
671 __ Bind(&done); 667 __ Bind(&done);
672 __ popl(EDX); // Remove pushed instantiator type arguments. 668 __ popl(EDX); // Remove pushed instantiator type arguments.
673 __ popl(ECX); // Remove pushed instantiator.
674 } 669 }
675 670
676 671
677 // Optimize assignable type check by adding inlined tests for: 672 // Optimize assignable type check by adding inlined tests for:
678 // - NULL -> return NULL. 673 // - NULL -> return NULL.
679 // - Smi -> compile time subtype check (only if dst class is not parameterized). 674 // - Smi -> compile time subtype check (only if dst class is not parameterized).
680 // - Class equality (only if class is not parameterized). 675 // - Class equality (only if class is not parameterized).
681 // Inputs: 676 // Inputs:
682 // - EAX: object. 677 // - EAX: object.
683 // - EDX: instantiator type arguments or raw_null. 678 // - EDX: instantiator type arguments or raw_null.
684 // - ECX: instantiator or raw_null.
685 // Returns: 679 // Returns:
686 // - object in EAX for successful assignable check (or throws TypeError). 680 // - object in EAX for successful assignable check (or throws TypeError).
687 // Performance notes: positive checks must be quick, negative checks can be slow 681 // Performance notes: positive checks must be quick, negative checks can be slow
688 // as they throw an exception. 682 // as they throw an exception.
689 void FlowGraphCompiler::GenerateAssertAssignable(intptr_t token_pos, 683 void FlowGraphCompiler::GenerateAssertAssignable(intptr_t token_pos,
690 intptr_t deopt_id, 684 intptr_t deopt_id,
691 const AbstractType& dst_type, 685 const AbstractType& dst_type,
692 const String& dst_name, 686 const String& dst_name,
693 LocationSummary* locs) { 687 LocationSummary* locs) {
694 ASSERT(token_pos >= 0); 688 ASSERT(token_pos >= 0);
695 ASSERT(!dst_type.IsNull()); 689 ASSERT(!dst_type.IsNull());
696 ASSERT(dst_type.IsFinalized()); 690 ASSERT(dst_type.IsFinalized());
697 // Assignable check is skipped in FlowGraphBuilder, not here. 691 // Assignable check is skipped in FlowGraphBuilder, not here.
698 ASSERT(dst_type.IsMalformedOrMalbounded() || 692 ASSERT(dst_type.IsMalformedOrMalbounded() ||
699 (!dst_type.IsDynamicType() && !dst_type.IsObjectType())); 693 (!dst_type.IsDynamicType() && !dst_type.IsObjectType()));
700 __ pushl(ECX); // Store instantiator.
701 __ pushl(EDX); // Store instantiator type arguments. 694 __ pushl(EDX); // Store instantiator type arguments.
702 // A null object is always assignable and is returned as result. 695 // A null object is always assignable and is returned as result.
703 const Immediate& raw_null = 696 const Immediate& raw_null =
704 Immediate(reinterpret_cast<intptr_t>(Object::null())); 697 Immediate(reinterpret_cast<intptr_t>(Object::null()));
705 Label is_assignable, runtime_call; 698 Label is_assignable, runtime_call;
706 __ cmpl(EAX, raw_null); 699 __ cmpl(EAX, raw_null);
707 __ j(EQUAL, &is_assignable); 700 __ j(EQUAL, &is_assignable);
708 701
709 // Generate throw new TypeError() if the type is malformed or malbounded. 702 // Generate throw new TypeError() if the type is malformed or malbounded.
710 if (dst_type.IsMalformedOrMalbounded()) { 703 if (dst_type.IsMalformedOrMalbounded()) {
711 __ PushObject(Object::null_object()); // Make room for the result. 704 __ PushObject(Object::null_object()); // Make room for the result.
712 __ pushl(EAX); // Push the source object. 705 __ pushl(EAX); // Push the source object.
713 __ PushObject(dst_name); // Push the name of the destination. 706 __ PushObject(dst_name); // Push the name of the destination.
714 __ PushObject(dst_type); // Push the type of the destination. 707 __ PushObject(dst_type); // Push the type of the destination.
715 GenerateRuntimeCall(token_pos, 708 GenerateRuntimeCall(token_pos,
716 deopt_id, 709 deopt_id,
717 kBadTypeErrorRuntimeEntry, 710 kBadTypeErrorRuntimeEntry,
718 3, 711 3,
719 locs); 712 locs);
720 // We should never return here. 713 // We should never return here.
721 __ int3(); 714 __ int3();
722 715
723 __ Bind(&is_assignable); // For a null object. 716 __ Bind(&is_assignable); // For a null object.
724 __ popl(EDX); // Remove pushed instantiator type arguments. 717 __ popl(EDX); // Remove pushed instantiator type arguments.
725 __ popl(ECX); // Remove pushed instantiator.
726 return; 718 return;
727 } 719 }
728 720
729 // Generate inline type check, linking to runtime call if not assignable. 721 // Generate inline type check, linking to runtime call if not assignable.
730 SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle(zone()); 722 SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle(zone());
731 test_cache = GenerateInlineInstanceof(token_pos, dst_type, 723 test_cache = GenerateInlineInstanceof(token_pos, dst_type,
732 &is_assignable, &runtime_call); 724 &is_assignable, &runtime_call);
733 725
734 __ Bind(&runtime_call); 726 __ Bind(&runtime_call);
735 __ movl(EDX, Address(ESP, 0)); // Get instantiator type arguments. 727 __ movl(EDX, Address(ESP, 0)); // Get instantiator type arguments.
736 __ movl(ECX, Address(ESP, kWordSize)); // Get instantiator.
737 __ PushObject(Object::null_object()); // Make room for the result. 728 __ PushObject(Object::null_object()); // Make room for the result.
738 __ pushl(EAX); // Push the source object. 729 __ pushl(EAX); // Push the source object.
739 __ PushObject(dst_type); // Push the type of the destination. 730 __ PushObject(dst_type); // Push the type of the destination.
740 __ pushl(ECX); // Instantiator.
741 __ pushl(EDX); // Instantiator type arguments. 731 __ pushl(EDX); // Instantiator type arguments.
742 __ PushObject(dst_name); // Push the name of the destination. 732 __ PushObject(dst_name); // Push the name of the destination.
743 __ LoadObject(EAX, test_cache); 733 __ LoadObject(EAX, test_cache);
744 __ pushl(EAX); 734 __ pushl(EAX);
745 GenerateRuntimeCall(token_pos, deopt_id, kTypeCheckRuntimeEntry, 6, locs); 735 GenerateRuntimeCall(token_pos, deopt_id, kTypeCheckRuntimeEntry, 5, locs);
746 // Pop the parameters supplied to the runtime entry. The result of the 736 // Pop the parameters supplied to the runtime entry. The result of the
747 // type check runtime call is the checked value. 737 // type check runtime call is the checked value.
748 __ Drop(6); 738 __ Drop(5);
749 __ popl(EAX); 739 __ popl(EAX);
750 740
751 __ Bind(&is_assignable); 741 __ Bind(&is_assignable);
752 __ popl(EDX); // Remove pushed instantiator type arguments. 742 __ popl(EDX); // Remove pushed instantiator type arguments.
753 __ popl(ECX); // Remove pushed instantiator.
754 } 743 }
755 744
756 745
757 void FlowGraphCompiler::EmitInstructionEpilogue(Instruction* instr) { 746 void FlowGraphCompiler::EmitInstructionEpilogue(Instruction* instr) {
758 if (is_optimizing()) { 747 if (is_optimizing()) {
759 return; 748 return;
760 } 749 }
761 Definition* defn = instr->AsDefinition(); 750 Definition* defn = instr->AsDefinition();
762 if ((defn != NULL) && defn->HasTemp()) { 751 if ((defn != NULL) && defn->HasTemp()) {
763 Location value = defn->locs()->out(0); 752 Location value = defn->locs()->out(0);
(...skipping 1085 matching lines...) Expand 10 before | Expand all | Expand 10 after
1849 __ movups(reg, Address(ESP, 0)); 1838 __ movups(reg, Address(ESP, 0));
1850 __ addl(ESP, Immediate(kFpuRegisterSize)); 1839 __ addl(ESP, Immediate(kFpuRegisterSize));
1851 } 1840 }
1852 1841
1853 1842
1854 #undef __ 1843 #undef __
1855 1844
1856 } // namespace dart 1845 } // namespace dart
1857 1846
1858 #endif // defined TARGET_ARCH_IA32 1847 #endif // defined TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_compiler_arm64.cc ('k') | runtime/vm/flow_graph_compiler_mips.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698