| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 596 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 607 Bailout("ReThrow Untested"); | 607 Bailout("ReThrow Untested"); |
| 608 } | 608 } |
| 609 | 609 |
| 610 | 610 |
| 611 void FlowGraphCompiler::VisitNativeLoadField(NativeLoadFieldComp* comp) { | 611 void FlowGraphCompiler::VisitNativeLoadField(NativeLoadFieldComp* comp) { |
| 612 __ popq(RAX); | 612 __ popq(RAX); |
| 613 __ movq(RAX, FieldAddress(RAX, comp->offset_in_bytes())); | 613 __ movq(RAX, FieldAddress(RAX, comp->offset_in_bytes())); |
| 614 } | 614 } |
| 615 | 615 |
| 616 | 616 |
| 617 void FlowGraphCompiler::VisitExtractTypeArguments( | 617 void FlowGraphCompiler::VisitExtractFactoryTypeArguments( |
| 618 ExtractTypeArgumentsComp* comp) { | 618 ExtractFactoryTypeArgumentsComp* comp) { |
| 619 __ popq(RAX); // Instantiator. | 619 __ popq(RAX); // Instantiator. |
| 620 if (!comp->constructor().IsFactory()) { | |
| 621 __ popq(RBX); // Discard placeholder. | |
| 622 } | |
| 623 | 620 |
| 624 // RAX is the instantiator AbstractTypeArguments object (or null). | 621 // RAX is the instantiator AbstractTypeArguments object (or null). |
| 625 // If RAX is null, no need to instantiate the type arguments, use null, and | 622 // If RAX is null, no need to instantiate the type arguments, use null, and |
| 626 // allocate an object of a raw type. | 623 // allocate an object of a raw type. |
| 627 const Immediate raw_null = | 624 const Immediate raw_null = |
| 628 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 625 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 629 Label type_arguments_instantiated, type_arguments_uninstantiated; | 626 Label type_arguments_instantiated, type_arguments_uninstantiated; |
| 630 __ cmpq(RAX, raw_null); | 627 __ cmpq(RAX, raw_null); |
| 631 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); | 628 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); |
| 632 | 629 |
| 633 // Instantiate non-null type arguments. | 630 // Instantiate non-null type arguments. |
| 634 if (comp->type_arguments().IsUninstantiatedIdentity()) { | 631 if (comp->type_arguments().IsUninstantiatedIdentity()) { |
| 635 // Check if the instantiator type argument vector is a TypeArguments of a | 632 // Check if the instantiator type argument vector is a TypeArguments of a |
| 636 // matching length and, if so, use it as the instantiated type_arguments. | 633 // matching length and, if so, use it as the instantiated type_arguments. |
| 637 __ LoadObject(RCX, Class::ZoneHandle(Object::type_arguments_class())); | 634 __ LoadObject(RCX, Class::ZoneHandle(Object::type_arguments_class())); |
| 638 __ cmpq(RCX, FieldAddress(RAX, Object::class_offset())); | 635 __ cmpq(RCX, FieldAddress(RAX, Object::class_offset())); |
| 639 __ j(NOT_EQUAL, &type_arguments_uninstantiated, Assembler::kNearJump); | 636 __ j(NOT_EQUAL, &type_arguments_uninstantiated, Assembler::kNearJump); |
| 640 Immediate arguments_length = Immediate(reinterpret_cast<int64_t>( | 637 Immediate arguments_length = Immediate(reinterpret_cast<int64_t>( |
| 641 Smi::New(comp->type_arguments().Length()))); | 638 Smi::New(comp->type_arguments().Length()))); |
| 642 __ cmpq(FieldAddress(RAX, TypeArguments::length_offset()), | 639 __ cmpq(FieldAddress(RAX, TypeArguments::length_offset()), |
| 643 arguments_length); | 640 arguments_length); |
| 644 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); | 641 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); |
| 645 } | 642 } |
| 646 __ Bind(&type_arguments_uninstantiated); | 643 __ Bind(&type_arguments_uninstantiated); |
| 647 if (comp->constructor().IsFactory()) { | 644 // A runtime call to instantiate the type arguments is required before |
| 648 // A runtime call to instantiate the type arguments is required before | 645 // calling the factory. |
| 649 // calling the factory. | 646 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
| 650 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 647 __ PushObject(comp->type_arguments()); |
| 651 __ PushObject(comp->type_arguments()); | 648 __ pushq(RAX); // Push instantiator type arguments. |
| 652 __ pushq(RAX); // Push instantiator type arguments. | 649 GenerateCallRuntime(comp->node_id(), |
| 653 GenerateCallRuntime(comp->node_id(), | 650 comp->token_index(), |
| 654 comp->token_index(), | 651 kInstantiateTypeArgumentsRuntimeEntry); |
| 655 kInstantiateTypeArgumentsRuntimeEntry); | 652 __ popq(RAX); // Pop instantiator type arguments. |
| 656 __ popq(RAX); // Pop instantiator type arguments. | 653 __ popq(RAX); // Pop uninstantiated type arguments. |
| 657 __ popq(RAX); // Pop uninstantiated type arguments. | 654 __ popq(RAX); // Pop instantiated type arguments. |
| 658 __ popq(RAX); // Pop instantiated type arguments. | 655 __ Bind(&type_arguments_instantiated); |
| 659 __ Bind(&type_arguments_instantiated); | 656 // RAX: Instantiated type arguments. |
| 660 // RAX: Instantiated type arguments. | |
| 661 } else { | |
| 662 // In the non-factory case, we rely on the allocation stub to | |
| 663 // instantiate the type arguments. | |
| 664 __ PushObject(comp->type_arguments()); | |
| 665 // RAX: Instantiator type arguments. | |
| 666 Label type_arguments_pushed; | |
| 667 __ jmp(&type_arguments_pushed, Assembler::kNearJump); | |
| 668 | |
| 669 __ Bind(&type_arguments_instantiated); | |
| 670 __ pushq(RAX); // Instantiated type arguments. | |
| 671 __ movq(RAX, raw_null); // Null instantiator. | |
| 672 __ Bind(&type_arguments_pushed); | |
| 673 } | |
| 674 } | 657 } |
| 675 | 658 |
| 676 | 659 |
| 660 void FlowGraphCompiler::VisitExtractConstructorTypeArguments( |
| 661 ExtractConstructorTypeArgumentsComp* comp) { |
| 662 __ popq(RAX); // Instantiator. |
| 663 |
| 664 // RAX is the instantiator AbstractTypeArguments object (or null). |
| 665 // If RAX is null, no need to instantiate the type arguments, use null, and |
| 666 // allocate an object of a raw type. |
| 667 // TODO(regis): The above sentence is actually not correct. If the type |
| 668 // arguments are only partially uninstantiated, we are losing type information |
| 669 // by allocating a raw type. The code needs to be fixed here and in the |
| 670 // unoptimized version (both ia32 and x64). |
| 671 const Immediate raw_null = |
| 672 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 673 Label type_arguments_instantiated, type_arguments_uninstantiated; |
| 674 __ cmpq(RAX, raw_null); |
| 675 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); |
| 676 |
| 677 // Check if type arguments represent the uninstantiated identity vector. |
| 678 if (comp->type_arguments().IsUninstantiatedIdentity()) { |
| 679 // Check if the instantiator type argument vector is a TypeArguments of a |
| 680 // matching length and, if so, use it as the instantiated type_arguments. |
| 681 __ LoadObject(RCX, Class::ZoneHandle(Object::type_arguments_class())); |
| 682 __ cmpq(RCX, FieldAddress(RAX, Object::class_offset())); |
| 683 __ j(NOT_EQUAL, &type_arguments_uninstantiated, Assembler::kNearJump); |
| 684 Immediate arguments_length = Immediate(reinterpret_cast<int64_t>( |
| 685 Smi::New(comp->type_arguments().Length()))); |
| 686 __ cmpq(FieldAddress(RAX, TypeArguments::length_offset()), |
| 687 arguments_length); |
| 688 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); |
| 689 } |
| 690 __ Bind(&type_arguments_uninstantiated); |
| 691 // In the non-factory case, we rely on the allocation stub to |
| 692 // instantiate the type arguments. |
| 693 __ LoadObject(RAX, comp->type_arguments()); |
| 694 // RAX: uninstantiated type arguments. |
| 695 __ Bind(&type_arguments_instantiated); |
| 696 // RAX: uninstantiated or instantiated type arguments. |
| 697 } |
| 698 |
| 699 |
| 700 void FlowGraphCompiler::VisitExtractConstructorInstantiator( |
| 701 ExtractConstructorInstantiatorComp* comp) { |
| 702 __ popq(RCX); // Discard value. |
| 703 __ popq(RAX); // Instantiator. |
| 704 |
| 705 // RAX is the instantiator AbstractTypeArguments object (or null). |
| 706 // If RAX is null, no need to instantiate the type arguments, use null, and |
| 707 // allocate an object of a raw type. |
| 708 // TODO(regis): The above sentence is actually not correct. If the type |
| 709 // arguments are only partially uninstantiated, we are losing type information |
| 710 // by allocating a raw type. The code needs to be fixed here and in the |
| 711 // unoptimized version (both ia32 and x64). |
| 712 |
| 713 // If type arguments represent the uninstantiated identity vector and if the |
| 714 // instantiator is not null, the instantiator was used as type arguments, |
| 715 // therefore, the instantiator must be reset to null here to indicate to the |
| 716 // allocator that the type arguments are instantiated. |
| 717 if (comp->type_arguments().IsUninstantiatedIdentity()) { |
| 718 // TODO(regis): The following emitted code is duplicated in |
| 719 // VisitExtractConstructorTypeArguments above. The reason is that the code |
| 720 // is split between two computations, so that each one produces a |
| 721 // single value, rather than producing a pair of values. |
| 722 // If this becomes an issue, we should expose these tests at the IL level. |
| 723 // Note that this code will still change, because bounds checking is not |
| 724 // implemented yet. |
| 725 const Immediate raw_null = |
| 726 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 727 Label use_instantiator; |
| 728 __ cmpq(RAX, raw_null); |
| 729 __ j(EQUAL, &use_instantiator, Assembler::kNearJump); // Already null. |
| 730 |
| 731 // Check if the instantiator type argument vector is a TypeArguments of a |
| 732 // matching length and, if so, use it as the instantiated type_arguments. |
| 733 __ LoadObject(RCX, Class::ZoneHandle(Object::type_arguments_class())); |
| 734 __ cmpq(RCX, FieldAddress(RAX, Object::class_offset())); |
| 735 __ j(NOT_EQUAL, &use_instantiator, Assembler::kNearJump); |
| 736 Immediate arguments_length = Immediate(reinterpret_cast<int64_t>( |
| 737 Smi::New(comp->type_arguments().Length()))); |
| 738 __ cmpq(FieldAddress(RAX, TypeArguments::length_offset()), |
| 739 arguments_length); |
| 740 __ j(NOT_EQUAL, &use_instantiator, Assembler::kNearJump); |
| 741 // The instantiator was used in VisitExtractConstructorTypeArguments as the |
| 742 // instantiated type arguments, reset instantiator to null. |
| 743 __ movq(RAX, raw_null); // Null instantiator. |
| 744 __ Bind(&use_instantiator); // Use instantiator in RAX. |
| 745 } |
| 746 // In the non-factory case, we rely on the allocation stub to |
| 747 // instantiate the type arguments. |
| 748 // RAX: instantiator or null. |
| 749 } |
| 750 |
| 751 |
| 677 void FlowGraphCompiler::VisitBlocks( | 752 void FlowGraphCompiler::VisitBlocks( |
| 678 const GrowableArray<BlockEntryInstr*>& blocks) { | 753 const GrowableArray<BlockEntryInstr*>& blocks) { |
| 679 for (intptr_t i = blocks.length() - 1; i >= 0; --i) { | 754 for (intptr_t i = blocks.length() - 1; i >= 0; --i) { |
| 680 // Compile the block entry. | 755 // Compile the block entry. |
| 681 current_block_ = blocks[i]; | 756 current_block_ = blocks[i]; |
| 682 Instruction* instr = current_block()->Accept(this); | 757 Instruction* instr = current_block()->Accept(this); |
| 683 // Compile all successors until an exit, branch, or a block entry. | 758 // Compile all successors until an exit, branch, or a block entry. |
| 684 while ((instr != NULL) && !instr->IsBlockEntry()) { | 759 while ((instr != NULL) && !instr->IsBlockEntry()) { |
| 685 instr = instr->Accept(this); | 760 instr = instr->Accept(this); |
| 686 } | 761 } |
| (...skipping 433 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1120 void FlowGraphCompiler::FinalizeExceptionHandlers(const Code& code) { | 1195 void FlowGraphCompiler::FinalizeExceptionHandlers(const Code& code) { |
| 1121 // We don't compile exception handlers yet. | 1196 // We don't compile exception handlers yet. |
| 1122 code.set_exception_handlers( | 1197 code.set_exception_handlers( |
| 1123 ExceptionHandlers::Handle(ExceptionHandlers::New(0))); | 1198 ExceptionHandlers::Handle(ExceptionHandlers::New(0))); |
| 1124 } | 1199 } |
| 1125 | 1200 |
| 1126 | 1201 |
| 1127 } // namespace dart | 1202 } // namespace dart |
| 1128 | 1203 |
| 1129 #endif // defined TARGET_ARCH_X64 | 1204 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |