| 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 467 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 478 | 478 |
| 479 const Class& type_class = Class::ZoneHandle(type.type_class()); | 479 const Class& type_class = Class::ZoneHandle(type.type_class()); |
| 480 const bool requires_type_arguments = type_class.HasTypeArguments(); | 480 const bool requires_type_arguments = type_class.HasTypeArguments(); |
| 481 // A Smi object cannot be the instance of a parameterized class. | 481 // A Smi object cannot be the instance of a parameterized class. |
| 482 // A class equality check is only applicable with a dst type of a | 482 // A class equality check is only applicable with a dst type of a |
| 483 // non-parameterized class or with a raw dst type of a parameterized class. | 483 // non-parameterized class or with a raw dst type of a parameterized class. |
| 484 if (requires_type_arguments) { | 484 if (requires_type_arguments) { |
| 485 const AbstractTypeArguments& type_arguments = | 485 const AbstractTypeArguments& type_arguments = |
| 486 AbstractTypeArguments::Handle(type.arguments()); | 486 AbstractTypeArguments::Handle(type.arguments()); |
| 487 const bool is_raw_type = type_arguments.IsNull() || | 487 const bool is_raw_type = type_arguments.IsNull() || |
| 488 type_arguments.IsDynamicTypes(type_arguments.Length()); | 488 type_arguments.IsRaw(type_arguments.Length()); |
| 489 Label runtime_call; | 489 Label runtime_call; |
| 490 __ testq(RAX, Immediate(kSmiTagMask)); | 490 __ testq(RAX, Immediate(kSmiTagMask)); |
| 491 __ j(ZERO, &runtime_call, Assembler::kNearJump); | 491 __ j(ZERO, &runtime_call, Assembler::kNearJump); |
| 492 // Object not Smi. | 492 // Object not Smi. |
| 493 if (is_raw_type) { | 493 if (is_raw_type) { |
| 494 if (type.IsListInterface()) { | 494 if (type.IsListInterface()) { |
| 495 Label push_result; | 495 Label push_result; |
| 496 // TODO(srdjan) also accept List<Object>. | 496 // TODO(srdjan) also accept List<Object>. |
| 497 __ movq(RCX, FieldAddress(RAX, Object::class_offset())); | 497 __ movq(RCX, FieldAddress(RAX, Object::class_offset())); |
| 498 __ CompareObject(RCX, *CoreClass("ObjectArray")); | 498 __ CompareObject(RCX, *CoreClass("ObjectArray")); |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 628 | 628 |
| 629 void FlowGraphCompiler::VisitCreateClosure(CreateClosureComp* comp) { | 629 void FlowGraphCompiler::VisitCreateClosure(CreateClosureComp* comp) { |
| 630 const Function& function = comp->function(); | 630 const Function& function = comp->function(); |
| 631 const Code& stub = Code::Handle( | 631 const Code& stub = Code::Handle( |
| 632 StubCode::GetAllocationStubForClosure(function)); | 632 StubCode::GetAllocationStubForClosure(function)); |
| 633 const ExternalLabel label(function.ToCString(), stub.EntryPoint()); | 633 const ExternalLabel label(function.ToCString(), stub.EntryPoint()); |
| 634 GenerateCall(comp->token_index(), &label, PcDescriptors::kOther); | 634 GenerateCall(comp->token_index(), &label, PcDescriptors::kOther); |
| 635 | 635 |
| 636 const Class& cls = Class::Handle(function.signature_class()); | 636 const Class& cls = Class::Handle(function.signature_class()); |
| 637 if (cls.HasTypeArguments()) { | 637 if (cls.HasTypeArguments()) { |
| 638 UNIMPLEMENTED(); // We should have bailed out. |
| 638 __ popq(RCX); // Discard type arguments. | 639 __ popq(RCX); // Discard type arguments. |
| 639 } | 640 } |
| 640 if (function.IsImplicitInstanceClosureFunction()) { | 641 if (function.IsImplicitInstanceClosureFunction()) { |
| 641 __ popq(RCX); // Discard receiver. | 642 __ popq(RCX); // Discard receiver. |
| 642 } | 643 } |
| 643 } | 644 } |
| 644 | 645 |
| 645 | 646 |
| 646 void FlowGraphCompiler::VisitNativeLoadField(NativeLoadFieldComp* comp) { | 647 void FlowGraphCompiler::VisitNativeLoadField(NativeLoadFieldComp* comp) { |
| 647 __ popq(RAX); | 648 __ popq(RAX); |
| 648 __ movq(RAX, FieldAddress(RAX, comp->offset_in_bytes())); | 649 __ movq(RAX, FieldAddress(RAX, comp->offset_in_bytes())); |
| 649 } | 650 } |
| 650 | 651 |
| 651 | 652 |
| 652 void FlowGraphCompiler::VisitExtractFactoryTypeArguments( | 653 void FlowGraphCompiler::VisitExtractFactoryTypeArguments( |
| 653 ExtractFactoryTypeArgumentsComp* comp) { | 654 ExtractFactoryTypeArgumentsComp* comp) { |
| 654 __ popq(RAX); // Instantiator. | 655 __ popq(RAX); // Instantiator. |
| 655 | 656 |
| 656 // RAX is the instantiator AbstractTypeArguments object (or null). | 657 // RAX is the instantiator AbstractTypeArguments object (or null). |
| 657 // If RAX is null, no need to instantiate the type arguments, use null, and | 658 // If the instantiator is null and if the type argument vector |
| 658 // allocate an object of a raw type. | 659 // instantiated from null becomes a vector of Dynamic, then use null as |
| 659 const Immediate raw_null = | 660 // the type arguments. |
| 660 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 661 Label type_arguments_instantiated; |
| 661 Label type_arguments_instantiated, type_arguments_uninstantiated; | 662 const intptr_t len = comp->type_arguments().Length(); |
| 662 __ cmpq(RAX, raw_null); | 663 if (comp->type_arguments().IsRawInstantiatedRaw(len)) { |
| 663 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); | 664 const Immediate raw_null = |
| 664 | 665 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 666 __ cmpq(RAX, raw_null); |
| 667 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); |
| 668 } |
| 665 // Instantiate non-null type arguments. | 669 // Instantiate non-null type arguments. |
| 666 if (comp->type_arguments().IsUninstantiatedIdentity()) { | 670 if (comp->type_arguments().IsUninstantiatedIdentity()) { |
| 671 Label type_arguments_uninstantiated; |
| 667 // Check if the instantiator type argument vector is a TypeArguments of a | 672 // Check if the instantiator type argument vector is a TypeArguments of a |
| 668 // matching length and, if so, use it as the instantiated type_arguments. | 673 // matching length and, if so, use it as the instantiated type_arguments. |
| 674 // No need to check the instantiator (RAX) for null here, because a null |
| 675 // instantiator will have the wrong class (Null instead of TypeArguments). |
| 669 __ LoadObject(RCX, Class::ZoneHandle(Object::type_arguments_class())); | 676 __ LoadObject(RCX, Class::ZoneHandle(Object::type_arguments_class())); |
| 670 __ cmpq(RCX, FieldAddress(RAX, Object::class_offset())); | 677 __ cmpq(RCX, FieldAddress(RAX, Object::class_offset())); |
| 671 __ j(NOT_EQUAL, &type_arguments_uninstantiated, Assembler::kNearJump); | 678 __ j(NOT_EQUAL, &type_arguments_uninstantiated, Assembler::kNearJump); |
| 672 Immediate arguments_length = Immediate(reinterpret_cast<int64_t>( | 679 Immediate arguments_length = Immediate(reinterpret_cast<int64_t>( |
| 673 Smi::New(comp->type_arguments().Length()))); | 680 Smi::New(comp->type_arguments().Length()))); |
| 674 __ cmpq(FieldAddress(RAX, TypeArguments::length_offset()), | 681 __ cmpq(FieldAddress(RAX, TypeArguments::length_offset()), |
| 675 arguments_length); | 682 arguments_length); |
| 676 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); | 683 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); |
| 684 __ Bind(&type_arguments_uninstantiated); |
| 677 } | 685 } |
| 678 __ Bind(&type_arguments_uninstantiated); | |
| 679 // A runtime call to instantiate the type arguments is required before | 686 // A runtime call to instantiate the type arguments is required before |
| 680 // calling the factory. | 687 // calling the factory. |
| 681 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 688 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
| 682 __ PushObject(comp->type_arguments()); | 689 __ PushObject(comp->type_arguments()); |
| 683 __ pushq(RAX); // Push instantiator type arguments. | 690 __ pushq(RAX); // Push instantiator type arguments. |
| 684 GenerateCallRuntime(comp->node_id(), | 691 GenerateCallRuntime(comp->node_id(), |
| 685 comp->token_index(), | 692 comp->token_index(), |
| 686 kInstantiateTypeArgumentsRuntimeEntry); | 693 kInstantiateTypeArgumentsRuntimeEntry); |
| 687 __ popq(RAX); // Pop instantiator type arguments. | 694 __ popq(RAX); // Pop instantiator type arguments. |
| 688 __ popq(RAX); // Pop uninstantiated type arguments. | 695 __ popq(RAX); // Pop uninstantiated type arguments. |
| 689 __ popq(RAX); // Pop instantiated type arguments. | 696 __ popq(RAX); // Pop instantiated type arguments. |
| 690 __ Bind(&type_arguments_instantiated); | 697 __ Bind(&type_arguments_instantiated); |
| 691 // RAX: Instantiated type arguments. | 698 // RAX: Instantiated type arguments. |
| 692 } | 699 } |
| 693 | 700 |
| 694 | 701 |
| 695 void FlowGraphCompiler::VisitExtractConstructorTypeArguments( | 702 void FlowGraphCompiler::VisitExtractConstructorTypeArguments( |
| 696 ExtractConstructorTypeArgumentsComp* comp) { | 703 ExtractConstructorTypeArgumentsComp* comp) { |
| 697 __ popq(RAX); // Instantiator. | 704 __ popq(RAX); // Instantiator. |
| 698 | 705 |
| 699 // RAX is the instantiator AbstractTypeArguments object (or null). | 706 // RAX is the instantiator AbstractTypeArguments object (or null). |
| 700 // If RAX is null, no need to instantiate the type arguments, use null, and | 707 // If the instantiator is null and if the type argument vector |
| 701 // allocate an object of a raw type. | 708 // instantiated from null becomes a vector of Dynamic, then use null as |
| 702 // TODO(regis): The above sentence is actually not correct. If the type | 709 // the type arguments. |
| 703 // arguments are only partially uninstantiated, we are losing type information | 710 Label type_arguments_instantiated; |
| 704 // by allocating a raw type. The code needs to be fixed here and in the | 711 const intptr_t len = comp->type_arguments().Length(); |
| 705 // unoptimized version (both ia32 and x64). | 712 if (comp->type_arguments().IsRawInstantiatedRaw(len)) { |
| 706 const Immediate raw_null = | 713 const Immediate raw_null = |
| 707 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 714 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 708 Label type_arguments_instantiated, type_arguments_uninstantiated; | 715 __ cmpq(RAX, raw_null); |
| 709 __ cmpq(RAX, raw_null); | 716 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); |
| 710 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); | 717 } |
| 711 | 718 // Instantiate non-null type arguments. |
| 712 // Check if type arguments represent the uninstantiated identity vector. | |
| 713 if (comp->type_arguments().IsUninstantiatedIdentity()) { | 719 if (comp->type_arguments().IsUninstantiatedIdentity()) { |
| 714 // Check if the instantiator type argument vector is a TypeArguments of a | 720 // Check if the instantiator type argument vector is a TypeArguments of a |
| 715 // matching length and, if so, use it as the instantiated type_arguments. | 721 // matching length and, if so, use it as the instantiated type_arguments. |
| 722 // No need to check the instantiator (RAX) for null here, because a null |
| 723 // instantiator will have the wrong class (Null instead of TypeArguments). |
| 724 Label type_arguments_uninstantiated; |
| 716 __ LoadObject(RCX, Class::ZoneHandle(Object::type_arguments_class())); | 725 __ LoadObject(RCX, Class::ZoneHandle(Object::type_arguments_class())); |
| 717 __ cmpq(RCX, FieldAddress(RAX, Object::class_offset())); | 726 __ cmpq(RCX, FieldAddress(RAX, Object::class_offset())); |
| 718 __ j(NOT_EQUAL, &type_arguments_uninstantiated, Assembler::kNearJump); | 727 __ j(NOT_EQUAL, &type_arguments_uninstantiated, Assembler::kNearJump); |
| 719 Immediate arguments_length = Immediate(reinterpret_cast<int64_t>( | 728 Immediate arguments_length = Immediate(reinterpret_cast<int64_t>( |
| 720 Smi::New(comp->type_arguments().Length()))); | 729 Smi::New(comp->type_arguments().Length()))); |
| 721 __ cmpq(FieldAddress(RAX, TypeArguments::length_offset()), | 730 __ cmpq(FieldAddress(RAX, TypeArguments::length_offset()), |
| 722 arguments_length); | 731 arguments_length); |
| 723 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); | 732 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); |
| 733 __ Bind(&type_arguments_uninstantiated); |
| 724 } | 734 } |
| 725 __ Bind(&type_arguments_uninstantiated); | |
| 726 // In the non-factory case, we rely on the allocation stub to | 735 // In the non-factory case, we rely on the allocation stub to |
| 727 // instantiate the type arguments. | 736 // instantiate the type arguments. |
| 728 __ LoadObject(RAX, comp->type_arguments()); | 737 __ LoadObject(RAX, comp->type_arguments()); |
| 729 // RAX: uninstantiated type arguments. | 738 // RAX: uninstantiated type arguments. |
| 730 __ Bind(&type_arguments_instantiated); | 739 __ Bind(&type_arguments_instantiated); |
| 731 // RAX: uninstantiated or instantiated type arguments. | 740 // RAX: uninstantiated or instantiated type arguments. |
| 732 } | 741 } |
| 733 | 742 |
| 734 | 743 |
| 735 void FlowGraphCompiler::VisitExtractConstructorInstantiator( | 744 void FlowGraphCompiler::VisitExtractConstructorInstantiator( |
| 736 ExtractConstructorInstantiatorComp* comp) { | 745 ExtractConstructorInstantiatorComp* comp) { |
| 737 __ popq(RCX); // Discard value. | 746 __ popq(RCX); // Discard value. |
| 738 __ popq(RAX); // Instantiator. | 747 __ popq(RAX); // Instantiator. |
| 739 | 748 |
| 740 // RAX is the instantiator AbstractTypeArguments object (or null). | 749 // RAX is the instantiator AbstractTypeArguments object (or null). |
| 741 // If RAX is null, no need to instantiate the type arguments, use null, and | 750 // If the instantiator is null and if the type argument vector |
| 742 // allocate an object of a raw type. | 751 // instantiated from null becomes a vector of Dynamic, then use null as |
| 743 // TODO(regis): The above sentence is actually not correct. If the type | 752 // the type arguments and do not pass the instantiator. |
| 744 // arguments are only partially uninstantiated, we are losing type information | 753 Label done; |
| 745 // by allocating a raw type. The code needs to be fixed here and in the | 754 const intptr_t len = comp->type_arguments().Length(); |
| 746 // unoptimized version (both ia32 and x64). | 755 if (comp->type_arguments().IsRawInstantiatedRaw(len)) { |
| 747 | 756 const Immediate raw_null = |
| 748 // If type arguments represent the uninstantiated identity vector and if the | 757 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 749 // instantiator is not null, the instantiator was used as type arguments, | 758 Label instantiator_not_null; |
| 750 // therefore, the instantiator must be reset to null here to indicate to the | 759 __ cmpq(RAX, raw_null); |
| 751 // allocator that the type arguments are instantiated. | 760 __ j(NOT_EQUAL, &instantiator_not_null, Assembler::kNearJump); |
| 761 // Null was used in VisitExtractConstructorTypeArguments as the |
| 762 // instantiated type arguments, no proper instantiator needed. |
| 763 __ movq(RAX, Immediate(Smi::RawValue(StubCode::kNoInstantiator))); |
| 764 __ jmp(&done); |
| 765 __ Bind(&instantiator_not_null); |
| 766 } |
| 767 // Instantiate non-null type arguments. |
| 752 if (comp->type_arguments().IsUninstantiatedIdentity()) { | 768 if (comp->type_arguments().IsUninstantiatedIdentity()) { |
| 753 // TODO(regis): The following emitted code is duplicated in | 769 // TODO(regis): The following emitted code is duplicated in |
| 754 // VisitExtractConstructorTypeArguments above. The reason is that the code | 770 // VisitExtractConstructorTypeArguments above. The reason is that the code |
| 755 // is split between two computations, so that each one produces a | 771 // is split between two computations, so that each one produces a |
| 756 // single value, rather than producing a pair of values. | 772 // single value, rather than producing a pair of values. |
| 757 // If this becomes an issue, we should expose these tests at the IL level. | 773 // If this becomes an issue, we should expose these tests at the IL level. |
| 758 // Note that this code will still change, because bounds checking is not | 774 // TODO(regis): This code will still change, because bounds checking is not |
| 759 // implemented yet. | 775 // implemented yet. |
| 760 const Immediate raw_null = | |
| 761 Immediate(reinterpret_cast<intptr_t>(Object::null())); | |
| 762 Label use_instantiator; | |
| 763 __ cmpq(RAX, raw_null); | |
| 764 __ j(EQUAL, &use_instantiator, Assembler::kNearJump); // Already null. | |
| 765 | 776 |
| 766 // Check if the instantiator type argument vector is a TypeArguments of a | 777 // Check if the instantiator type argument vector is a TypeArguments of a |
| 767 // matching length and, if so, use it as the instantiated type_arguments. | 778 // matching length and, if so, use it as the instantiated type_arguments. |
| 779 // No need to check the instantiator (RAX) for null here, because a null |
| 780 // instantiator will have the wrong class (Null instead of TypeArguments). |
| 768 __ LoadObject(RCX, Class::ZoneHandle(Object::type_arguments_class())); | 781 __ LoadObject(RCX, Class::ZoneHandle(Object::type_arguments_class())); |
| 769 __ cmpq(RCX, FieldAddress(RAX, Object::class_offset())); | 782 __ cmpq(RCX, FieldAddress(RAX, Object::class_offset())); |
| 770 __ j(NOT_EQUAL, &use_instantiator, Assembler::kNearJump); | 783 __ j(NOT_EQUAL, &done, Assembler::kNearJump); |
| 771 Immediate arguments_length = Immediate(reinterpret_cast<int64_t>( | 784 Immediate arguments_length = Immediate(reinterpret_cast<int64_t>( |
| 772 Smi::New(comp->type_arguments().Length()))); | 785 Smi::New(comp->type_arguments().Length()))); |
| 773 __ cmpq(FieldAddress(RAX, TypeArguments::length_offset()), | 786 __ cmpq(FieldAddress(RAX, TypeArguments::length_offset()), |
| 774 arguments_length); | 787 arguments_length); |
| 775 __ j(NOT_EQUAL, &use_instantiator, Assembler::kNearJump); | 788 __ j(NOT_EQUAL, &done, Assembler::kNearJump); |
| 776 // The instantiator was used in VisitExtractConstructorTypeArguments as the | 789 // The instantiator was used in VisitExtractConstructorTypeArguments as the |
| 777 // instantiated type arguments, reset instantiator to null. | 790 // instantiated type arguments, no proper instantiator needed. |
| 778 __ movq(RAX, raw_null); // Null instantiator. | 791 __ movq(RAX, Immediate(Smi::RawValue(StubCode::kNoInstantiator))); |
| 779 __ Bind(&use_instantiator); // Use instantiator in RAX. | |
| 780 } | 792 } |
| 781 // In the non-factory case, we rely on the allocation stub to | 793 __ Bind(&done); |
| 782 // instantiate the type arguments. | 794 // RAX: instantiator or kNoInstantiator. |
| 783 // RAX: instantiator or null. | |
| 784 } | 795 } |
| 785 | 796 |
| 786 | 797 |
| 787 void FlowGraphCompiler::VisitAllocateContext(AllocateContextComp* comp) { | 798 void FlowGraphCompiler::VisitAllocateContext(AllocateContextComp* comp) { |
| 788 __ movq(R10, Immediate(comp->num_context_variables())); | 799 __ movq(R10, Immediate(comp->num_context_variables())); |
| 789 const ExternalLabel label("alloc_context", | 800 const ExternalLabel label("alloc_context", |
| 790 StubCode::AllocateContextEntryPoint()); | 801 StubCode::AllocateContextEntryPoint()); |
| 791 GenerateCall(comp->token_index(), &label, PcDescriptors::kOther); | 802 GenerateCall(comp->token_index(), &label, PcDescriptors::kOther); |
| 792 } | 803 } |
| 793 | 804 |
| (...skipping 476 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1270 void FlowGraphCompiler::FinalizeExceptionHandlers(const Code& code) { | 1281 void FlowGraphCompiler::FinalizeExceptionHandlers(const Code& code) { |
| 1271 // We don't compile exception handlers yet. | 1282 // We don't compile exception handlers yet. |
| 1272 code.set_exception_handlers( | 1283 code.set_exception_handlers( |
| 1273 ExceptionHandlers::Handle(ExceptionHandlers::New(0))); | 1284 ExceptionHandlers::Handle(ExceptionHandlers::New(0))); |
| 1274 } | 1285 } |
| 1275 | 1286 |
| 1276 | 1287 |
| 1277 } // namespace dart | 1288 } // namespace dart |
| 1278 | 1289 |
| 1279 #endif // defined TARGET_ARCH_X64 | 1290 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |