Chromium Code Reviews| 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 "lib/error.h" | 10 #include "lib/error.h" |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 80 try_index_); | 80 try_index_); |
| 81 #undef __ | 81 #undef __ |
| 82 } | 82 } |
| 83 | 83 |
| 84 | 84 |
| 85 FlowGraphCompiler::FlowGraphCompiler( | 85 FlowGraphCompiler::FlowGraphCompiler( |
| 86 Assembler* assembler, | 86 Assembler* assembler, |
| 87 const ParsedFunction& parsed_function, | 87 const ParsedFunction& parsed_function, |
| 88 const GrowableArray<BlockEntryInstr*>& block_order, | 88 const GrowableArray<BlockEntryInstr*>& block_order, |
| 89 bool is_optimizing) | 89 bool is_optimizing) |
| 90 : FlowGraphVisitor(block_order), | 90 : FlowGraphCompilerShared(parsed_function, block_order.length()), |
| 91 assembler_(assembler), | 91 assembler_(assembler), |
| 92 parsed_function_(parsed_function), | 92 block_order_(block_order), |
| 93 block_info_(block_order.length()), | |
| 94 current_block_(NULL), | 93 current_block_(NULL), |
| 95 pc_descriptors_list_(NULL), | |
| 96 stackmap_builder_(NULL), | |
| 97 exception_handlers_list_(NULL), | |
| 98 deopt_stubs_(), | 94 deopt_stubs_(), |
| 99 is_optimizing_(is_optimizing) { | 95 is_optimizing_(is_optimizing) { |
| 100 } | 96 } |
| 101 | 97 |
| 102 | 98 |
| 103 void FlowGraphCompiler::InitCompiler() { | |
| 104 pc_descriptors_list_ = new DescriptorList(); | |
| 105 exception_handlers_list_ = new ExceptionHandlerList(); | |
| 106 block_info_.Clear(); | |
| 107 for (int i = 0; i < block_order_.length(); ++i) { | |
| 108 block_info_.Add(new BlockInfo()); | |
| 109 } | |
| 110 } | |
| 111 | |
| 112 | |
| 113 FlowGraphCompiler::~FlowGraphCompiler() { | |
| 114 // BlockInfos are zone-allocated, so their destructors are not called. | |
| 115 // Verify the labels explicitly here. | |
| 116 for (int i = 0; i < block_info_.length(); ++i) { | |
| 117 ASSERT(!block_info_[i]->label.IsLinked()); | |
| 118 ASSERT(!block_info_[i]->label.HasNear()); | |
| 119 } | |
| 120 } | |
| 121 | |
| 122 | |
| 123 intptr_t FlowGraphCompiler::StackSize() const { | 99 intptr_t FlowGraphCompiler::StackSize() const { |
| 124 return parsed_function_.stack_local_count() + | 100 return parsed_function().stack_local_count() + |
| 125 parsed_function_.copied_parameter_count(); | 101 parsed_function().copied_parameter_count(); |
| 126 } | 102 } |
| 127 | 103 |
| 128 | 104 |
| 129 void FlowGraphCompiler::Bailout(const char* reason) { | 105 void FlowGraphCompiler::Bailout(const char* reason) { |
| 130 const char* kFormat = "FlowGraphCompiler Bailout: %s %s."; | 106 const char* kFormat = "FlowGraphCompiler Bailout: %s %s."; |
| 131 const char* function_name = parsed_function_.function().ToCString(); | 107 const char* function_name = parsed_function().function().ToCString(); |
| 132 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1; | 108 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1; |
| 133 char* chars = reinterpret_cast<char*>( | 109 char* chars = reinterpret_cast<char*>( |
| 134 Isolate::Current()->current_zone()->Allocate(len)); | 110 Isolate::Current()->current_zone()->Allocate(len)); |
| 135 OS::SNPrint(chars, len, kFormat, function_name, reason); | 111 OS::SNPrint(chars, len, kFormat, function_name, reason); |
| 136 const Error& error = Error::Handle( | 112 const Error& error = Error::Handle( |
| 137 LanguageError::New(String::Handle(String::New(chars)))); | 113 LanguageError::New(String::Handle(String::New(chars)))); |
| 138 Isolate::Current()->long_jump_base()->Jump(1, error); | 114 Isolate::Current()->long_jump_base()->Jump(1, error); |
| 139 } | 115 } |
| 140 | 116 |
| 141 | 117 |
| (...skipping 473 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 615 } else { | 591 } else { |
| 616 __ LoadObject(dst, value->AsConstant()->value()); | 592 __ LoadObject(dst, value->AsConstant()->value()); |
| 617 } | 593 } |
| 618 } else { | 594 } else { |
| 619 ASSERT(value->IsUse()); | 595 ASSERT(value->IsUse()); |
| 620 __ popq(dst); | 596 __ popq(dst); |
| 621 } | 597 } |
| 622 } | 598 } |
| 623 | 599 |
| 624 | 600 |
| 625 void FlowGraphCompiler::VisitUse(UseVal* val) { | |
| 626 // UseVal is never visited during code generation. | |
| 627 UNREACHABLE(); | |
| 628 } | |
| 629 | |
| 630 | |
| 631 void FlowGraphCompiler::VisitConstant(ConstantVal* val) { | |
| 632 // Moved to intermediate_language_x64.cc. | |
| 633 UNREACHABLE(); | |
| 634 } | |
| 635 | |
| 636 | |
| 637 void FlowGraphCompiler::VisitAssertAssignable(AssertAssignableComp* comp) { | |
| 638 // Moved to intermediate_language_x64.cc. | |
| 639 UNREACHABLE(); | |
| 640 } | |
| 641 | |
| 642 | |
| 643 void FlowGraphCompiler::VisitAssertBoolean(AssertBooleanComp* comp) { | |
| 644 // Moved to intermediate_language_x64.cc. | |
| 645 UNREACHABLE(); | |
| 646 } | |
| 647 | |
| 648 | |
| 649 void FlowGraphCompiler::EmitInstanceCall(intptr_t cid, | 601 void FlowGraphCompiler::EmitInstanceCall(intptr_t cid, |
| 650 intptr_t token_index, | 602 intptr_t token_index, |
| 651 intptr_t try_index, | 603 intptr_t try_index, |
| 652 const String& function_name, | 604 const String& function_name, |
| 653 intptr_t argument_count, | 605 intptr_t argument_count, |
| 654 const Array& argument_names, | 606 const Array& argument_names, |
| 655 intptr_t checked_argument_count) { | 607 intptr_t checked_argument_count) { |
| 656 ICData& ic_data = | 608 ICData& ic_data = |
| 657 ICData::ZoneHandle(ICData::New(parsed_function_.function(), | 609 ICData::ZoneHandle(ICData::New(parsed_function().function(), |
| 658 function_name, | 610 function_name, |
| 659 cid, | 611 cid, |
| 660 checked_argument_count)); | 612 checked_argument_count)); |
| 661 const Array& arguments_descriptor = | 613 const Array& arguments_descriptor = |
| 662 CodeGenerator::ArgumentsDescriptor(argument_count, argument_names); | 614 CodeGenerator::ArgumentsDescriptor(argument_count, argument_names); |
| 663 __ LoadObject(RBX, ic_data); | 615 __ LoadObject(RBX, ic_data); |
| 664 __ LoadObject(R10, arguments_descriptor); | 616 __ LoadObject(R10, arguments_descriptor); |
| 665 | 617 |
| 666 uword label_address = 0; | 618 uword label_address = 0; |
| 667 switch (checked_argument_count) { | 619 switch (checked_argument_count) { |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 692 __ LoadObject(R10, arguments_descriptor); | 644 __ LoadObject(R10, arguments_descriptor); |
| 693 | 645 |
| 694 GenerateCall(token_index, | 646 GenerateCall(token_index, |
| 695 try_index, | 647 try_index, |
| 696 &StubCode::CallStaticFunctionLabel(), | 648 &StubCode::CallStaticFunctionLabel(), |
| 697 PcDescriptors::kFuncCall); | 649 PcDescriptors::kFuncCall); |
| 698 __ Drop(argument_count); | 650 __ Drop(argument_count); |
| 699 } | 651 } |
| 700 | 652 |
| 701 | 653 |
| 702 void FlowGraphCompiler::VisitCurrentContext(CurrentContextComp* comp) { | |
| 703 // Moved to intermediate_language_x64.cc. | |
| 704 UNREACHABLE(); | |
| 705 } | |
| 706 | |
| 707 | |
| 708 void FlowGraphCompiler::VisitStoreContext(StoreContextComp* comp) { | |
| 709 // Moved to intermediate_language_x64.cc. | |
| 710 UNREACHABLE(); | |
| 711 } | |
| 712 | |
| 713 | |
| 714 void FlowGraphCompiler::VisitClosureCall(ClosureCallComp* comp) { | |
| 715 // Moved to intermediate_language_x64.cc. | |
| 716 UNREACHABLE(); | |
| 717 } | |
| 718 | |
| 719 | |
| 720 void FlowGraphCompiler::VisitInstanceCall(InstanceCallComp* comp) { | |
| 721 // Moved to intermediate_language_x64.cc. | |
| 722 UNREACHABLE(); | |
| 723 } | |
| 724 | |
| 725 | |
| 726 void FlowGraphCompiler::VisitStrictCompare(StrictCompareComp* comp) { | |
| 727 // Moved to intermediate_language_x64.cc. | |
| 728 UNREACHABLE(); | |
| 729 } | |
| 730 | |
| 731 | |
| 732 void FlowGraphCompiler::VisitEqualityCompare(EqualityCompareComp* comp) { | |
| 733 // Moved to intermediate_language_x64.cc. | |
| 734 UNREACHABLE(); | |
| 735 } | |
| 736 | |
| 737 | |
| 738 void FlowGraphCompiler::VisitStaticCall(StaticCallComp* comp) { | |
| 739 // Moved to intermediate_language_x64.cc. | |
| 740 UNREACHABLE(); | |
| 741 } | |
| 742 | |
| 743 | |
| 744 void FlowGraphCompiler::VisitLoadLocal(LoadLocalComp* comp) { | |
| 745 // Moved to intermediate_language_x64.cc. | |
| 746 UNREACHABLE(); | |
| 747 } | |
| 748 | |
| 749 | |
| 750 void FlowGraphCompiler::VisitStoreLocal(StoreLocalComp* comp) { | |
| 751 // Moved to intermediate_language_x64.cc. | |
| 752 UNREACHABLE(); | |
| 753 } | |
| 754 | |
| 755 | |
| 756 void FlowGraphCompiler::VisitNativeCall(NativeCallComp* comp) { | |
| 757 // Moved to intermediate_language_x64.cc. | |
| 758 UNREACHABLE(); | |
| 759 } | |
| 760 | |
| 761 | |
| 762 void FlowGraphCompiler::VisitLoadInstanceField(LoadInstanceFieldComp* comp) { | |
| 763 // Moved to intermediate_language_x64.cc. | |
| 764 UNREACHABLE(); | |
| 765 } | |
| 766 | |
| 767 | |
| 768 void FlowGraphCompiler::VisitStoreInstanceField(StoreInstanceFieldComp* comp) { | |
| 769 // Moved to intermediate_language_x64.cc. | |
| 770 UNREACHABLE(); | |
| 771 } | |
| 772 | |
| 773 | |
| 774 | |
| 775 void FlowGraphCompiler::VisitLoadStaticField(LoadStaticFieldComp* comp) { | |
| 776 // Moved to intermediate_language_x64.cc. | |
| 777 UNREACHABLE(); | |
| 778 } | |
| 779 | |
| 780 | |
| 781 void FlowGraphCompiler::VisitStoreStaticField(StoreStaticFieldComp* comp) { | |
| 782 // Moved to intermediate_language_x64.cc. | |
| 783 UNREACHABLE(); | |
| 784 } | |
| 785 | |
| 786 | |
| 787 void FlowGraphCompiler::VisitStoreIndexed(StoreIndexedComp* comp) { | |
| 788 // Moved to intermediate_language_x64.cc. | |
| 789 UNREACHABLE(); | |
| 790 } | |
| 791 | |
| 792 | |
| 793 void FlowGraphCompiler::VisitInstanceSetter(InstanceSetterComp* comp) { | |
| 794 // Moved to intermediate_language_x64.cc. | |
| 795 UNREACHABLE(); | |
| 796 } | |
| 797 | |
| 798 | |
| 799 void FlowGraphCompiler::VisitStaticSetter(StaticSetterComp* comp) { | |
| 800 // Moved to intermediate_language_x64.cc. | |
| 801 UNREACHABLE(); | |
| 802 } | |
| 803 | |
| 804 | |
| 805 void FlowGraphCompiler::VisitBooleanNegate(BooleanNegateComp* comp) { | |
| 806 // Moved to intermediate_language_x64.cc. | |
| 807 UNREACHABLE(); | |
| 808 } | |
| 809 | |
| 810 | |
| 811 // Optimize instanceof type test by adding inlined tests for: | 654 // Optimize instanceof type test by adding inlined tests for: |
| 812 // - NULL -> return false. | 655 // - NULL -> return false. |
| 813 // - Smi -> compile time subtype check (only if dst class is not parameterized). | 656 // - Smi -> compile time subtype check (only if dst class is not parameterized). |
| 814 // - Class equality (only if class is not parameterized). | 657 // - Class equality (only if class is not parameterized). |
| 815 // Inputs: | 658 // Inputs: |
| 816 // - RAX: object. | 659 // - RAX: object. |
| 817 // - RDX: instantiator type arguments or raw_null. | 660 // - RDX: instantiator type arguments or raw_null. |
| 818 // - RCX: instantiator or raw_null. | 661 // - RCX: instantiator or raw_null. |
| 819 // Destroys RCX and RDX. | 662 // Destroys RCX and RDX. |
| 820 // Returns: | 663 // Returns: |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 885 __ jmp(&done, Assembler::kNearJump); | 728 __ jmp(&done, Assembler::kNearJump); |
| 886 | 729 |
| 887 __ Bind(&is_instance); | 730 __ Bind(&is_instance); |
| 888 __ LoadObject(RAX, negate_result ? bool_false : bool_true); | 731 __ LoadObject(RAX, negate_result ? bool_false : bool_true); |
| 889 __ Bind(&done); | 732 __ Bind(&done); |
| 890 __ popq(RDX); // Remove pushed instantiator type arguments.. | 733 __ popq(RDX); // Remove pushed instantiator type arguments.. |
| 891 __ popq(RCX); // Remove pushed instantiator. | 734 __ popq(RCX); // Remove pushed instantiator. |
| 892 } | 735 } |
| 893 | 736 |
| 894 | 737 |
| 895 void FlowGraphCompiler::VisitInstanceOf(InstanceOfComp* comp) { | |
| 896 // Moved to intermediate_language_x64.cc. | |
| 897 UNREACHABLE(); | |
| 898 } | |
| 899 | |
| 900 | |
| 901 void FlowGraphCompiler::VisitAllocateObject(AllocateObjectComp* comp) { | |
| 902 // Moved to intermediate_language_x64.cc. | |
| 903 UNREACHABLE(); | |
| 904 } | |
| 905 | |
| 906 | |
| 907 void FlowGraphCompiler::VisitAllocateObjectWithBoundsCheck( | |
| 908 AllocateObjectWithBoundsCheckComp* comp) { | |
| 909 // Moved to intermediate_language_x64.cc. | |
| 910 UNREACHABLE(); | |
| 911 } | |
| 912 | |
| 913 | |
| 914 void FlowGraphCompiler::VisitCreateArray(CreateArrayComp* comp) { | |
| 915 // Moved to intermediate_language_x64.cc. | |
| 916 UNREACHABLE(); | |
| 917 } | |
| 918 | |
| 919 | |
| 920 void FlowGraphCompiler::VisitCreateClosure(CreateClosureComp* comp) { | |
| 921 // Moved to intermediate_language_x64.cc. | |
| 922 UNREACHABLE(); | |
| 923 } | |
| 924 | |
| 925 | |
| 926 void FlowGraphCompiler::VisitLoadVMField(LoadVMFieldComp* comp) { | |
| 927 // Moved to intermediate_language_x64.cc. | |
| 928 UNREACHABLE(); | |
| 929 } | |
| 930 | |
| 931 | |
| 932 void FlowGraphCompiler::VisitStoreVMField(StoreVMFieldComp* comp) { | |
| 933 // Moved to intermediate_language_x64.cc. | |
| 934 UNREACHABLE(); | |
| 935 } | |
| 936 | |
| 937 | |
| 938 void FlowGraphCompiler::VisitInstantiateTypeArguments( | |
| 939 InstantiateTypeArgumentsComp* comp) { | |
| 940 // Moved to intermediate_language_x64.cc. | |
| 941 UNREACHABLE(); | |
| 942 } | |
| 943 | |
| 944 | |
| 945 void FlowGraphCompiler::VisitExtractConstructorTypeArguments( | |
| 946 ExtractConstructorTypeArgumentsComp* comp) { | |
| 947 // Moved to intermediate_language_x64.cc. | |
| 948 UNREACHABLE(); | |
| 949 } | |
| 950 | |
| 951 | |
| 952 void FlowGraphCompiler::VisitExtractConstructorInstantiator( | |
| 953 ExtractConstructorInstantiatorComp* comp) { | |
| 954 // Moved to intermediate_language_x64.cc. | |
| 955 UNREACHABLE(); | |
| 956 } | |
| 957 | |
| 958 | |
| 959 void FlowGraphCompiler::VisitAllocateContext(AllocateContextComp* comp) { | |
| 960 // Moved to intermediate_language_x64.cc. | |
| 961 UNREACHABLE(); | |
| 962 } | |
| 963 | |
| 964 | |
| 965 void FlowGraphCompiler::VisitChainContext(ChainContextComp* comp) { | |
| 966 // Moved to intermediate_language_x64.cc. | |
| 967 UNREACHABLE(); | |
| 968 } | |
| 969 | |
| 970 | |
| 971 void FlowGraphCompiler::VisitCloneContext(CloneContextComp* comp) { | |
| 972 // Moved to intermediate_language_x64.cc. | |
| 973 UNREACHABLE(); | |
| 974 } | |
| 975 | |
| 976 | |
| 977 void FlowGraphCompiler::VisitCatchEntry(CatchEntryComp* comp) { | |
| 978 // Moved to intermediate_language_x64.cc. | |
| 979 UNREACHABLE(); | |
| 980 } | |
| 981 | |
| 982 | |
| 983 void FlowGraphCompiler::VisitBinaryOp(BinaryOpComp* comp) { | |
| 984 UNIMPLEMENTED(); | |
| 985 } | |
| 986 | |
| 987 | |
| 988 void FlowGraphCompiler::VisitUnarySmiOp(UnarySmiOpComp* comp) { | |
| 989 UNIMPLEMENTED(); | |
| 990 } | |
| 991 | |
| 992 | |
| 993 void FlowGraphCompiler::VisitNumberNegate(NumberNegateComp* comp) { | |
| 994 UNIMPLEMENTED(); | |
| 995 } | |
| 996 | |
| 997 | |
| 998 void FlowGraphCompiler::EmitInstructionPrologue(Instruction* instr) { | 738 void FlowGraphCompiler::EmitInstructionPrologue(Instruction* instr) { |
| 999 LocationSummary* locs = instr->locs(); | 739 LocationSummary* locs = instr->locs(); |
| 1000 ASSERT(locs != NULL); | 740 ASSERT(locs != NULL); |
| 1001 | 741 |
| 1002 locs->AllocateRegisters(); | 742 locs->AllocateRegisters(); |
| 1003 | 743 |
| 1004 // Load instruction inputs into allocated registers. | 744 // Load instruction inputs into allocated registers. |
| 1005 for (intptr_t i = locs->input_count() - 1; i >= 0; i--) { | 745 for (intptr_t i = locs->input_count() - 1; i >= 0; i--) { |
| 1006 Location loc = locs->in(i); | 746 Location loc = locs->in(i); |
| 1007 ASSERT(loc.kind() == Location::kRegister); | 747 ASSERT(loc.kind() == Location::kRegister); |
| 1008 __ popq(loc.reg()); | 748 __ popq(loc.reg()); |
| 1009 } | 749 } |
| 1010 } | 750 } |
| 1011 | 751 |
| 1012 | 752 |
| 1013 void FlowGraphCompiler::VisitBlocks() { | 753 void FlowGraphCompiler::VisitBlocks() { |
| 1014 for (intptr_t i = 0; i < block_order_.length(); ++i) { | 754 for (intptr_t i = 0; i < block_order_.length(); ++i) { |
| 1015 __ Comment("B%d", i); | 755 __ Comment("B%d", i); |
| 1016 // Compile the block entry. | 756 // Compile the block entry. |
| 1017 current_block_ = block_order_[i]; | 757 current_block_ = block_order_[i]; |
| 1018 Instruction* instr = current_block()->Accept(this); | 758 current_block_->EmitNativeCode(this); |
|
Vyacheslav Egorov (Google)
2012/06/01 10:55:24
This is extremely confusing to read, if I did not
srdjan
2012/06/01 17:44:47
Agreed with readability problem, needs at least a
| |
| 759 Instruction* instr = current_block_->StraightLineSuccessor(); | |
| 1019 // Compile all successors until an exit, branch, or a block entry. | 760 // Compile all successors until an exit, branch, or a block entry. |
| 1020 while ((instr != NULL) && !instr->IsBlockEntry()) { | 761 while ((instr != NULL) && !instr->IsBlockEntry()) { |
| 1021 if (FLAG_code_comments) EmitComment(instr); | 762 if (FLAG_code_comments) EmitComment(instr); |
| 1022 if (instr->locs() != NULL) { | 763 ASSERT(instr->locs() != NULL); |
| 1023 EmitInstructionPrologue(instr); | 764 EmitInstructionPrologue(instr); |
| 1024 instr->EmitNativeCode(this); | 765 instr->EmitNativeCode(this); |
| 1025 instr = instr->StraightLineSuccessor(); | 766 instr = instr->StraightLineSuccessor(); |
| 1026 } else { | |
| 1027 instr = instr->Accept(this); | |
| 1028 } | |
| 1029 } | 767 } |
| 1030 | 768 |
| 1031 BlockEntryInstr* successor = | 769 BlockEntryInstr* successor = |
| 1032 (instr == NULL) ? NULL : instr->AsBlockEntry(); | 770 (instr == NULL) ? NULL : instr->AsBlockEntry(); |
| 1033 if (successor != NULL) { | 771 if (successor != NULL) { |
| 1034 // Block ended with a "goto". We can fall through if it is the | 772 // Block ended with a "goto". We can fall through if it is the |
| 1035 // next block in the list. Otherwise, we need a jump. | 773 // next block in the list. Otherwise, we need a jump. |
| 1036 if ((i == block_order_.length() - 1) || | 774 if ((i == block_order_.length() - 1) || |
| 1037 (block_order_[i + 1] != successor)) { | 775 (block_order_[i + 1] != successor)) { |
| 1038 __ jmp(&block_info_[successor->postorder_number()]->label); | 776 __ jmp(&block_info()[successor->postorder_number()]->label); |
|
Vyacheslav Egorov (Google)
2012/06/01 10:55:24
use GetLabelFor?
srdjan
2012/06/01 17:44:47
Done.
| |
| 1039 } | 777 } |
| 1040 } | 778 } |
| 1041 } | 779 } |
| 1042 } | 780 } |
| 1043 | 781 |
| 1044 | 782 |
| 1045 void FlowGraphCompiler::EmitComment(Instruction* instr) { | 783 void FlowGraphCompiler::EmitComment(Instruction* instr) { |
| 1046 char buffer[80]; | 784 char buffer[80]; |
| 1047 BufferFormatter f(buffer, sizeof(buffer)); | 785 BufferFormatter f(buffer, sizeof(buffer)); |
| 1048 instr->PrintTo(&f); | 786 instr->PrintTo(&f); |
| 1049 __ Comment("@%d: %s", instr->cid(), buffer); | 787 __ Comment("@%d: %s", instr->cid(), buffer); |
| 1050 } | 788 } |
| 1051 | 789 |
| 1052 | 790 |
| 1053 void FlowGraphCompiler::VisitGraphEntry(GraphEntryInstr* instr) { | |
| 1054 // Nothing to do. | |
| 1055 } | |
| 1056 | |
| 1057 | |
| 1058 void FlowGraphCompiler::VisitJoinEntry(JoinEntryInstr* instr) { | |
| 1059 __ Bind(&block_info_[instr->postorder_number()]->label); | |
| 1060 } | |
| 1061 | |
| 1062 | |
| 1063 void FlowGraphCompiler::VisitTargetEntry(TargetEntryInstr* instr) { | |
| 1064 __ Bind(&block_info_[instr->postorder_number()]->label); | |
| 1065 if (instr->HasTryIndex()) { | |
| 1066 exception_handlers_list_->AddHandler(instr->try_index(), | |
| 1067 assembler_->CodeSize()); | |
| 1068 } | |
| 1069 } | |
| 1070 | |
| 1071 | |
| 1072 void FlowGraphCompiler::VisitDo(DoInstr* instr) { | |
| 1073 instr->computation()->Accept(this); | |
| 1074 } | |
| 1075 | |
| 1076 | |
| 1077 void FlowGraphCompiler::VisitBind(BindInstr* instr) { | |
| 1078 // Moved to intermediate_language_x64.cc. | |
| 1079 UNREACHABLE(); | |
| 1080 } | |
| 1081 | |
| 1082 | |
| 1083 void FlowGraphCompiler::VisitReturn(ReturnInstr* instr) { | |
| 1084 // Moved to intermediate_language_x64.cc. | |
| 1085 UNREACHABLE(); | |
| 1086 } | |
| 1087 | |
| 1088 | |
| 1089 void FlowGraphCompiler::VisitThrow(ThrowInstr* instr) { | |
| 1090 // Moved to intermediate_language_x64.cc. | |
| 1091 UNREACHABLE(); | |
| 1092 } | |
| 1093 | |
| 1094 | |
| 1095 void FlowGraphCompiler::VisitReThrow(ReThrowInstr* instr) { | |
| 1096 // Moved to intermediate_language_x64.cc. | |
| 1097 UNREACHABLE(); | |
| 1098 } | |
| 1099 | |
| 1100 | |
| 1101 | |
| 1102 void FlowGraphCompiler::VisitBranch(BranchInstr* instr) { | |
| 1103 // Moved to intermediate_language_x64.cc. | |
| 1104 UNREACHABLE(); | |
| 1105 } | |
| 1106 | |
| 1107 | |
| 1108 // Copied from CodeGenerator::CopyParameters (CodeGenerator will be deprecated). | 791 // Copied from CodeGenerator::CopyParameters (CodeGenerator will be deprecated). |
| 1109 void FlowGraphCompiler::CopyParameters() { | 792 void FlowGraphCompiler::CopyParameters() { |
| 1110 const Function& function = parsed_function_.function(); | 793 const Function& function = parsed_function().function(); |
| 1111 LocalScope* scope = parsed_function_.node_sequence()->scope(); | 794 LocalScope* scope = parsed_function().node_sequence()->scope(); |
| 1112 const int num_fixed_params = function.num_fixed_parameters(); | 795 const int num_fixed_params = function.num_fixed_parameters(); |
| 1113 const int num_opt_params = function.num_optional_parameters(); | 796 const int num_opt_params = function.num_optional_parameters(); |
| 1114 ASSERT(parsed_function_.first_parameter_index() == | 797 ASSERT(parsed_function().first_parameter_index() == |
| 1115 ParsedFunction::kFirstLocalSlotIndex); | 798 ParsedFunction::kFirstLocalSlotIndex); |
| 1116 // Copy positional arguments. | 799 // Copy positional arguments. |
| 1117 // Check that no fewer than num_fixed_params positional arguments are passed | 800 // Check that no fewer than num_fixed_params positional arguments are passed |
| 1118 // in and that no more than num_params arguments are passed in. | 801 // in and that no more than num_params arguments are passed in. |
| 1119 // Passed argument i at fp[1 + argc - i] | 802 // Passed argument i at fp[1 + argc - i] |
| 1120 // copied to fp[ParsedFunction::kFirstLocalSlotIndex - i]. | 803 // copied to fp[ParsedFunction::kFirstLocalSlotIndex - i]. |
| 1121 const int num_params = num_fixed_params + num_opt_params; | 804 const int num_params = num_fixed_params + num_opt_params; |
| 1122 | 805 |
| 1123 // Total number of args is the first Smi in args descriptor array (R10). | 806 // Total number of args is the first Smi in args descriptor array (R10). |
| 1124 __ movq(RBX, FieldAddress(R10, Array::data_offset())); | 807 __ movq(RBX, FieldAddress(R10, Array::data_offset())); |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1205 // fp[1 + argc - arg_pos]. | 888 // fp[1 + argc - arg_pos]. |
| 1206 __ movq(RAX, Address(RDI, kWordSize)); // RAX is arg_pos as Smi. | 889 __ movq(RAX, Address(RDI, kWordSize)); // RAX is arg_pos as Smi. |
| 1207 __ addq(RDI, Immediate(2 * kWordSize)); // Point to next name/pos pair. | 890 __ addq(RDI, Immediate(2 * kWordSize)); // Point to next name/pos pair. |
| 1208 __ negq(RAX); | 891 __ negq(RAX); |
| 1209 Address argument_addr(RBX, RAX, TIMES_4, 0); // RAX is a negative Smi. | 892 Address argument_addr(RBX, RAX, TIMES_4, 0); // RAX is a negative Smi. |
| 1210 __ movq(RAX, argument_addr); | 893 __ movq(RAX, argument_addr); |
| 1211 __ jmp(&assign_optional_parameter, Assembler::kNearJump); | 894 __ jmp(&assign_optional_parameter, Assembler::kNearJump); |
| 1212 __ Bind(&load_default_value); | 895 __ Bind(&load_default_value); |
| 1213 // Load RAX with default argument at pos. | 896 // Load RAX with default argument at pos. |
| 1214 const Object& value = Object::ZoneHandle( | 897 const Object& value = Object::ZoneHandle( |
| 1215 parsed_function_.default_parameter_values().At( | 898 parsed_function().default_parameter_values().At( |
| 1216 param_pos - num_fixed_params)); | 899 param_pos - num_fixed_params)); |
| 1217 __ LoadObject(RAX, value); | 900 __ LoadObject(RAX, value); |
| 1218 __ Bind(&assign_optional_parameter); | 901 __ Bind(&assign_optional_parameter); |
| 1219 // Assign RAX to fp[ParsedFunction::kFirstLocalSlotIndex - param_pos]. | 902 // Assign RAX to fp[ParsedFunction::kFirstLocalSlotIndex - param_pos]. |
| 1220 // We do not use the final allocation index of the variable here, i.e. | 903 // We do not use the final allocation index of the variable here, i.e. |
| 1221 // scope->VariableAt(i)->index(), because captured variables still need | 904 // scope->VariableAt(i)->index(), because captured variables still need |
| 1222 // to be copied to the context that is not yet allocated. | 905 // to be copied to the context that is not yet allocated. |
| 1223 const Address param_addr( | 906 const Address param_addr( |
| 1224 RBP, (ParsedFunction::kFirstLocalSlotIndex - param_pos) * kWordSize); | 907 RBP, (ParsedFunction::kFirstLocalSlotIndex - param_pos) * kWordSize); |
| 1225 __ movq(param_addr, RAX); | 908 __ movq(param_addr, RAX); |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 1243 } | 926 } |
| 1244 if (function.IsClosureFunction()) { | 927 if (function.IsClosureFunction()) { |
| 1245 GenerateCallRuntime(AstNode::kNoId, | 928 GenerateCallRuntime(AstNode::kNoId, |
| 1246 0, | 929 0, |
| 1247 CatchClauseNode::kInvalidTryIndex, | 930 CatchClauseNode::kInvalidTryIndex, |
| 1248 kClosureArgumentMismatchRuntimeEntry); | 931 kClosureArgumentMismatchRuntimeEntry); |
| 1249 } else { | 932 } else { |
| 1250 // Invoke noSuchMethod function. | 933 // Invoke noSuchMethod function. |
| 1251 const int kNumArgsChecked = 1; | 934 const int kNumArgsChecked = 1; |
| 1252 ICData& ic_data = ICData::ZoneHandle(); | 935 ICData& ic_data = ICData::ZoneHandle(); |
| 1253 ic_data = ICData::New(parsed_function_.function(), | 936 ic_data = ICData::New(parsed_function().function(), |
| 1254 String::Handle(function.name()), | 937 String::Handle(function.name()), |
| 1255 AstNode::kNoId, | 938 AstNode::kNoId, |
| 1256 kNumArgsChecked); | 939 kNumArgsChecked); |
| 1257 __ LoadObject(RBX, ic_data); | 940 __ LoadObject(RBX, ic_data); |
| 1258 // RBP - 8 : PC marker, allows easy identification of RawInstruction obj. | 941 // RBP - 8 : PC marker, allows easy identification of RawInstruction obj. |
| 1259 // RBP : points to previous frame pointer. | 942 // RBP : points to previous frame pointer. |
| 1260 // RBP + 8 : points to return address. | 943 // RBP + 8 : points to return address. |
| 1261 // RBP + 16 : address of last argument (arg n-1). | 944 // RBP + 16 : address of last argument (arg n-1). |
| 1262 // RSP + 16 + 8*(n-1) : address of first argument (arg 0). | 945 // RSP + 16 + 8*(n-1) : address of first argument (arg 0). |
| 1263 // RBX : ic-data. | 946 // RBX : ic-data. |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1305 !FLAG_report_usage_count && | 988 !FLAG_report_usage_count && |
| 1306 (FLAG_optimization_counter_threshold >= 0) && | 989 (FLAG_optimization_counter_threshold >= 0) && |
| 1307 !Isolate::Current()->debugger()->IsActive(); | 990 !Isolate::Current()->debugger()->IsActive(); |
| 1308 } | 991 } |
| 1309 | 992 |
| 1310 | 993 |
| 1311 void FlowGraphCompiler::IntrinsifyGetter() { | 994 void FlowGraphCompiler::IntrinsifyGetter() { |
| 1312 // TOS: return address. | 995 // TOS: return address. |
| 1313 // +1 : receiver. | 996 // +1 : receiver. |
| 1314 // Sequence node has one return node, its input is load field node. | 997 // Sequence node has one return node, its input is load field node. |
| 1315 const SequenceNode& sequence_node = *parsed_function_.node_sequence(); | 998 const SequenceNode& sequence_node = *parsed_function().node_sequence(); |
| 1316 ASSERT(sequence_node.length() == 1); | 999 ASSERT(sequence_node.length() == 1); |
| 1317 ASSERT(sequence_node.NodeAt(0)->IsReturnNode()); | 1000 ASSERT(sequence_node.NodeAt(0)->IsReturnNode()); |
| 1318 const ReturnNode& return_node = *sequence_node.NodeAt(0)->AsReturnNode(); | 1001 const ReturnNode& return_node = *sequence_node.NodeAt(0)->AsReturnNode(); |
| 1319 ASSERT(return_node.value()->IsLoadInstanceFieldNode()); | 1002 ASSERT(return_node.value()->IsLoadInstanceFieldNode()); |
| 1320 const LoadInstanceFieldNode& load_node = | 1003 const LoadInstanceFieldNode& load_node = |
| 1321 *return_node.value()->AsLoadInstanceFieldNode(); | 1004 *return_node.value()->AsLoadInstanceFieldNode(); |
| 1322 __ movq(RAX, Address(RSP, 1 * kWordSize)); | 1005 __ movq(RAX, Address(RSP, 1 * kWordSize)); |
| 1323 __ movq(RAX, FieldAddress(RAX, load_node.field().Offset())); | 1006 __ movq(RAX, FieldAddress(RAX, load_node.field().Offset())); |
| 1324 __ ret(); | 1007 __ ret(); |
| 1325 } | 1008 } |
| 1326 | 1009 |
| 1327 | 1010 |
| 1328 void FlowGraphCompiler::IntrinsifySetter() { | 1011 void FlowGraphCompiler::IntrinsifySetter() { |
| 1329 // TOS: return address. | 1012 // TOS: return address. |
| 1330 // +1 : value | 1013 // +1 : value |
| 1331 // +2 : receiver. | 1014 // +2 : receiver. |
| 1332 // Sequence node has one store node and one return NULL node. | 1015 // Sequence node has one store node and one return NULL node. |
| 1333 const SequenceNode& sequence_node = *parsed_function_.node_sequence(); | 1016 const SequenceNode& sequence_node = *parsed_function().node_sequence(); |
| 1334 ASSERT(sequence_node.length() == 2); | 1017 ASSERT(sequence_node.length() == 2); |
| 1335 ASSERT(sequence_node.NodeAt(0)->IsStoreInstanceFieldNode()); | 1018 ASSERT(sequence_node.NodeAt(0)->IsStoreInstanceFieldNode()); |
| 1336 ASSERT(sequence_node.NodeAt(1)->IsReturnNode()); | 1019 ASSERT(sequence_node.NodeAt(1)->IsReturnNode()); |
| 1337 const StoreInstanceFieldNode& store_node = | 1020 const StoreInstanceFieldNode& store_node = |
| 1338 *sequence_node.NodeAt(0)->AsStoreInstanceFieldNode(); | 1021 *sequence_node.NodeAt(0)->AsStoreInstanceFieldNode(); |
| 1339 __ movq(RAX, Address(RSP, 2 * kWordSize)); // Receiver. | 1022 __ movq(RAX, Address(RSP, 2 * kWordSize)); // Receiver. |
| 1340 __ movq(RBX, Address(RSP, 1 * kWordSize)); // Value. | 1023 __ movq(RBX, Address(RSP, 1 * kWordSize)); // Value. |
| 1341 __ StoreIntoObject(RAX, FieldAddress(RAX, store_node.field().Offset()), RBX); | 1024 __ StoreIntoObject(RAX, FieldAddress(RAX, store_node.field().Offset()), RBX); |
| 1342 const Immediate raw_null = | 1025 const Immediate raw_null = |
| 1343 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 1026 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 1344 __ movq(RAX, raw_null); | 1027 __ movq(RAX, raw_null); |
| 1345 __ ret(); | 1028 __ ret(); |
| 1346 } | 1029 } |
| 1347 | 1030 |
| 1348 | 1031 |
| 1349 // Returns 'true' if code generation for this function is complete, i.e., | 1032 // Returns 'true' if code generation for this function is complete, i.e., |
| 1350 // no fall-through to regular code is needed. | 1033 // no fall-through to regular code is needed. |
| 1351 bool FlowGraphCompiler::TryIntrinsify() { | 1034 bool FlowGraphCompiler::TryIntrinsify() { |
| 1352 if (!CanOptimize()) return false; | 1035 if (!CanOptimize()) return false; |
| 1353 // Intrinsification skips arguments checks, therefore disable if in checked | 1036 // Intrinsification skips arguments checks, therefore disable if in checked |
| 1354 // mode. | 1037 // mode. |
| 1355 if (FLAG_intrinsify && !FLAG_trace_functions && !FLAG_enable_type_checks) { | 1038 if (FLAG_intrinsify && !FLAG_trace_functions && !FLAG_enable_type_checks) { |
| 1356 if ((parsed_function_.function().kind() == RawFunction::kImplicitGetter)) { | 1039 if ((parsed_function().function().kind() == RawFunction::kImplicitGetter)) { |
| 1357 IntrinsifyGetter(); | 1040 IntrinsifyGetter(); |
| 1358 return true; | 1041 return true; |
| 1359 } | 1042 } |
| 1360 if ((parsed_function_.function().kind() == RawFunction::kImplicitSetter)) { | 1043 if ((parsed_function().function().kind() == RawFunction::kImplicitSetter)) { |
| 1361 IntrinsifySetter(); | 1044 IntrinsifySetter(); |
| 1362 return true; | 1045 return true; |
| 1363 } | 1046 } |
| 1364 } | 1047 } |
| 1365 // Even if an intrinsified version of the function was successfully | 1048 // Even if an intrinsified version of the function was successfully |
| 1366 // generated, it may fall through to the non-intrinsified method body. | 1049 // generated, it may fall through to the non-intrinsified method body. |
| 1367 if (!FLAG_trace_functions) { | 1050 if (!FLAG_trace_functions) { |
| 1368 return Intrinsifier::Intrinsify(parsed_function_.function(), assembler_); | 1051 return Intrinsifier::Intrinsify(parsed_function().function(), assembler_); |
| 1369 } | 1052 } |
| 1370 return false; | 1053 return false; |
| 1371 } | 1054 } |
| 1372 | 1055 |
| 1373 | 1056 |
| 1374 void FlowGraphCompiler::CompileGraph() { | 1057 void FlowGraphCompiler::CompileGraph() { |
| 1375 InitCompiler(); | 1058 InitCompiler(); |
| 1376 if (TryIntrinsify()) { | 1059 if (TryIntrinsify()) { |
| 1377 // Make it patchable: code must have a minimum code size, nop(2) increases | 1060 // Make it patchable: code must have a minimum code size, nop(2) increases |
| 1378 // the minimum code size appropriately. | 1061 // the minimum code size appropriately. |
| 1379 __ nop(2); | 1062 __ nop(2); |
| 1380 __ int3(); | 1063 __ int3(); |
| 1381 __ jmp(&StubCode::FixCallersTargetLabel()); | 1064 __ jmp(&StubCode::FixCallersTargetLabel()); |
| 1382 return; | 1065 return; |
| 1383 } | 1066 } |
| 1384 // Specialized version of entry code from CodeGenerator::GenerateEntryCode. | 1067 // Specialized version of entry code from CodeGenerator::GenerateEntryCode. |
| 1385 const Function& function = parsed_function_.function(); | 1068 const Function& function = parsed_function().function(); |
| 1386 | 1069 |
| 1387 const int parameter_count = function.num_fixed_parameters(); | 1070 const int parameter_count = function.num_fixed_parameters(); |
| 1388 const int num_copied_params = parsed_function_.copied_parameter_count(); | 1071 const int num_copied_params = parsed_function().copied_parameter_count(); |
| 1389 const int local_count = parsed_function_.stack_local_count(); | 1072 const int local_count = parsed_function().stack_local_count(); |
| 1390 AssemblerMacros::EnterDartFrame(assembler_, (StackSize() * kWordSize)); | 1073 AssemblerMacros::EnterDartFrame(assembler_, (StackSize() * kWordSize)); |
| 1391 | 1074 |
| 1392 // We check the number of passed arguments when we have to copy them due to | 1075 // We check the number of passed arguments when we have to copy them due to |
| 1393 // the presence of optional named parameters. | 1076 // the presence of optional named parameters. |
| 1394 // No such checking code is generated if only fixed parameters are declared, | 1077 // No such checking code is generated if only fixed parameters are declared, |
| 1395 // unless we are debug mode or unless we are compiling a closure. | 1078 // unless we are debug mode or unless we are compiling a closure. |
| 1396 if (num_copied_params == 0) { | 1079 if (num_copied_params == 0) { |
| 1397 #ifdef DEBUG | 1080 #ifdef DEBUG |
| 1398 const bool check_arguments = true; | 1081 const bool check_arguments = true; |
| 1399 #else | 1082 #else |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 1416 } | 1099 } |
| 1417 __ Bind(&argc_in_range); | 1100 __ Bind(&argc_in_range); |
| 1418 } | 1101 } |
| 1419 } else { | 1102 } else { |
| 1420 CopyParameters(); | 1103 CopyParameters(); |
| 1421 } | 1104 } |
| 1422 | 1105 |
| 1423 // Initialize locals to null. | 1106 // Initialize locals to null. |
| 1424 if (local_count > 0) { | 1107 if (local_count > 0) { |
| 1425 __ movq(RAX, Immediate(reinterpret_cast<intptr_t>(Object::null()))); | 1108 __ movq(RAX, Immediate(reinterpret_cast<intptr_t>(Object::null()))); |
| 1426 const int base = parsed_function_.first_stack_local_index(); | 1109 const int base = parsed_function().first_stack_local_index(); |
| 1427 for (int i = 0; i < local_count; ++i) { | 1110 for (int i = 0; i < local_count; ++i) { |
| 1428 // Subtract index i (locals lie at lower addresses than RBP). | 1111 // Subtract index i (locals lie at lower addresses than RBP). |
| 1429 __ movq(Address(RBP, (base - i) * kWordSize), RAX); | 1112 __ movq(Address(RBP, (base - i) * kWordSize), RAX); |
| 1430 } | 1113 } |
| 1431 } | 1114 } |
| 1432 | 1115 |
| 1433 // Generate stack overflow check. | 1116 // Generate stack overflow check. |
| 1434 __ movq(TMP, Immediate(Isolate::Current()->stack_limit_address())); | 1117 __ movq(TMP, Immediate(Isolate::Current()->stack_limit_address())); |
| 1435 __ cmpq(RSP, Address(TMP, 0)); | 1118 __ cmpq(RSP, Address(TMP, 0)); |
| 1436 Label no_stack_overflow; | 1119 Label no_stack_overflow; |
| 1437 __ j(ABOVE, &no_stack_overflow, Assembler::kNearJump); | 1120 __ j(ABOVE, &no_stack_overflow, Assembler::kNearJump); |
| 1438 GenerateCallRuntime(AstNode::kNoId, | 1121 GenerateCallRuntime(AstNode::kNoId, |
| 1439 function.token_index(), | 1122 function.token_index(), |
| 1440 CatchClauseNode::kInvalidTryIndex, | 1123 CatchClauseNode::kInvalidTryIndex, |
| 1441 kStackOverflowRuntimeEntry); | 1124 kStackOverflowRuntimeEntry); |
| 1442 __ Bind(&no_stack_overflow); | 1125 __ Bind(&no_stack_overflow); |
| 1443 | 1126 |
| 1444 if (FLAG_print_scopes) { | 1127 if (FLAG_print_scopes) { |
| 1445 // Print the function scope (again) after generating the prologue in order | 1128 // Print the function scope (again) after generating the prologue in order |
| 1446 // to see annotations such as allocation indices of locals. | 1129 // to see annotations such as allocation indices of locals. |
| 1447 if (FLAG_print_ast) { | 1130 if (FLAG_print_ast) { |
| 1448 // Second printing. | 1131 // Second printing. |
| 1449 OS::Print("Annotated "); | 1132 OS::Print("Annotated "); |
| 1450 } | 1133 } |
| 1451 AstPrinter::PrintFunctionScope(parsed_function_); | 1134 AstPrinter::PrintFunctionScope(parsed_function()); |
| 1452 } | 1135 } |
| 1453 | 1136 |
| 1454 VisitBlocks(); | 1137 VisitBlocks(); |
| 1455 | 1138 |
| 1456 __ int3(); | 1139 __ int3(); |
| 1457 GenerateDeferredCode(); | 1140 GenerateDeferredCode(); |
| 1458 // Emit function patching code. This will be swapped with the first 13 bytes | 1141 // Emit function patching code. This will be swapped with the first 13 bytes |
| 1459 // at entry point. | 1142 // at entry point. |
| 1460 pc_descriptors_list_->AddDescriptor(PcDescriptors::kPatchCode, | 1143 pc_descriptors_list()->AddDescriptor(PcDescriptors::kPatchCode, |
| 1461 assembler_->CodeSize(), | 1144 assembler_->CodeSize(), |
| 1462 AstNode::kNoId, | 1145 AstNode::kNoId, |
| 1463 0, | 1146 0, |
| 1464 -1); | 1147 -1); |
| 1465 __ jmp(&StubCode::FixCallersTargetLabel()); | 1148 __ jmp(&StubCode::FixCallersTargetLabel()); |
| 1466 } | 1149 } |
| 1467 | 1150 |
| 1468 | 1151 |
| 1469 void FlowGraphCompiler::GenerateDeferredCode() { | 1152 void FlowGraphCompiler::GenerateDeferredCode() { |
| 1470 for (intptr_t i = 0; i < deopt_stubs_.length(); i++) { | 1153 for (intptr_t i = 0; i < deopt_stubs_.length(); i++) { |
| 1471 deopt_stubs_[i]->GenerateCode(this); | 1154 deopt_stubs_[i]->GenerateCode(this); |
| 1472 } | 1155 } |
| 1473 } | 1156 } |
| 1474 | 1157 |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 1490 __ CallRuntime(entry); | 1173 __ CallRuntime(entry); |
| 1491 AddCurrentDescriptor(PcDescriptors::kOther, cid, token_index, try_index); | 1174 AddCurrentDescriptor(PcDescriptors::kOther, cid, token_index, try_index); |
| 1492 } | 1175 } |
| 1493 | 1176 |
| 1494 | 1177 |
| 1495 // Uses current pc position and try-index. | 1178 // Uses current pc position and try-index. |
| 1496 void FlowGraphCompiler::AddCurrentDescriptor(PcDescriptors::Kind kind, | 1179 void FlowGraphCompiler::AddCurrentDescriptor(PcDescriptors::Kind kind, |
| 1497 intptr_t cid, | 1180 intptr_t cid, |
| 1498 intptr_t token_index, | 1181 intptr_t token_index, |
| 1499 intptr_t try_index) { | 1182 intptr_t try_index) { |
| 1500 pc_descriptors_list_->AddDescriptor(kind, | 1183 pc_descriptors_list()->AddDescriptor(kind, |
| 1501 assembler_->CodeSize(), | 1184 assembler_->CodeSize(), |
| 1502 cid, | 1185 cid, |
| 1503 token_index, | 1186 token_index, |
| 1504 try_index); | 1187 try_index); |
| 1505 } | 1188 } |
| 1506 | 1189 |
| 1507 | 1190 |
| 1508 Label* FlowGraphCompiler::AddDeoptStub(intptr_t deopt_id, | 1191 Label* FlowGraphCompiler::AddDeoptStub(intptr_t deopt_id, |
| 1509 intptr_t deopt_token_index, | 1192 intptr_t deopt_token_index, |
| 1510 intptr_t try_index, | 1193 intptr_t try_index, |
| 1511 DeoptReasonId reason, | 1194 DeoptReasonId reason, |
| 1512 Register reg1, | 1195 Register reg1, |
| 1513 Register reg2) { | 1196 Register reg2) { |
| 1514 DeoptimizationStub* stub = | 1197 DeoptimizationStub* stub = |
| 1515 new DeoptimizationStub(deopt_id, deopt_token_index, try_index, reason); | 1198 new DeoptimizationStub(deopt_id, deopt_token_index, try_index, reason); |
| 1516 stub->Push(reg1); | 1199 stub->Push(reg1); |
| 1517 stub->Push(reg2); | 1200 stub->Push(reg2); |
| 1518 deopt_stubs_.Add(stub); | 1201 deopt_stubs_.Add(stub); |
| 1519 return stub->entry_label(); | 1202 return stub->entry_label(); |
| 1520 } | 1203 } |
| 1521 | 1204 |
| 1522 | 1205 |
| 1523 void FlowGraphCompiler::FinalizePcDescriptors(const Code& code) { | |
| 1524 ASSERT(pc_descriptors_list_ != NULL); | |
| 1525 const PcDescriptors& descriptors = PcDescriptors::Handle( | |
| 1526 pc_descriptors_list_->FinalizePcDescriptors(code.EntryPoint())); | |
| 1527 descriptors.Verify(parsed_function_.function().is_optimizable()); | |
| 1528 code.set_pc_descriptors(descriptors); | |
| 1529 } | |
| 1530 | |
| 1531 | |
| 1532 void FlowGraphCompiler::FinalizeStackmaps(const Code& code) { | |
| 1533 if (stackmap_builder_ == NULL) { | |
| 1534 // The unoptimizing compiler has no stack maps. | |
| 1535 code.set_stackmaps(Array::Handle()); | |
| 1536 } else { | |
| 1537 // Finalize the stack map array and add it to the code object. | |
| 1538 code.set_stackmaps( | |
| 1539 Array::Handle(stackmap_builder_->FinalizeStackmaps(code))); | |
| 1540 } | |
| 1541 } | |
| 1542 | |
| 1543 | |
| 1544 void FlowGraphCompiler::FinalizeVarDescriptors(const Code& code) { | |
| 1545 const LocalVarDescriptors& var_descs = LocalVarDescriptors::Handle( | |
| 1546 parsed_function_.node_sequence()->scope()->GetVarDescriptors()); | |
| 1547 code.set_var_descriptors(var_descs); | |
| 1548 } | |
| 1549 | |
| 1550 | |
| 1551 void FlowGraphCompiler::FinalizeExceptionHandlers(const Code& code) { | |
| 1552 ASSERT(exception_handlers_list_ != NULL); | |
| 1553 const ExceptionHandlers& handlers = ExceptionHandlers::Handle( | |
| 1554 exception_handlers_list_->FinalizeExceptionHandlers(code.EntryPoint())); | |
| 1555 code.set_exception_handlers(handlers); | |
| 1556 } | |
| 1557 | |
| 1558 | |
| 1559 void FlowGraphCompiler::FinalizeComments(const Code& code) { | 1206 void FlowGraphCompiler::FinalizeComments(const Code& code) { |
| 1560 code.set_comments(assembler_->GetCodeComments()); | 1207 code.set_comments(assembler_->GetCodeComments()); |
| 1561 } | 1208 } |
| 1562 | 1209 |
| 1563 #undef __ | 1210 #undef __ |
| 1564 | 1211 |
| 1565 } // namespace dart | 1212 } // namespace dart |
| 1566 | 1213 |
| 1567 #endif // defined TARGET_ARCH_X64 | 1214 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |