OLD | NEW |
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_XXX. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_XXX. |
6 | 6 |
7 #include "vm/flow_graph_compiler.h" | 7 #include "vm/flow_graph_compiler.h" |
8 | 8 |
9 #include "vm/bit_vector.h" | 9 #include "vm/bit_vector.h" |
10 #include "vm/cha.h" | 10 #include "vm/cha.h" |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
48 DECLARE_FLAG(int, optimization_counter_threshold); | 48 DECLARE_FLAG(int, optimization_counter_threshold); |
49 DECLARE_FLAG(bool, propagate_ic_data); | 49 DECLARE_FLAG(bool, propagate_ic_data); |
50 DECLARE_FLAG(int, regexp_optimization_counter_threshold); | 50 DECLARE_FLAG(int, regexp_optimization_counter_threshold); |
51 DECLARE_FLAG(int, reoptimization_counter_threshold); | 51 DECLARE_FLAG(int, reoptimization_counter_threshold); |
52 DECLARE_FLAG(int, stacktrace_every); | 52 DECLARE_FLAG(int, stacktrace_every); |
53 DECLARE_FLAG(charp, stacktrace_filter); | 53 DECLARE_FLAG(charp, stacktrace_filter); |
54 DECLARE_FLAG(bool, use_cha); | 54 DECLARE_FLAG(bool, use_cha); |
55 DECLARE_FLAG(bool, use_osr); | 55 DECLARE_FLAG(bool, use_osr); |
56 DECLARE_FLAG(bool, warn_on_javascript_compatibility); | 56 DECLARE_FLAG(bool, warn_on_javascript_compatibility); |
57 | 57 |
58 // Quick access to the locally defined isolate() method. | |
59 #define I (isolate()) | |
60 | |
61 // Assign locations to incoming arguments, i.e., values pushed above spill slots | 58 // Assign locations to incoming arguments, i.e., values pushed above spill slots |
62 // with PushArgument. Recursively allocates from outermost to innermost | 59 // with PushArgument. Recursively allocates from outermost to innermost |
63 // environment. | 60 // environment. |
64 void CompilerDeoptInfo::AllocateIncomingParametersRecursive( | 61 void CompilerDeoptInfo::AllocateIncomingParametersRecursive( |
65 Environment* env, | 62 Environment* env, |
66 intptr_t* stack_height) { | 63 intptr_t* stack_height) { |
67 if (env == NULL) return; | 64 if (env == NULL) return; |
68 AllocateIncomingParametersRecursive(env->outer(), stack_height); | 65 AllocateIncomingParametersRecursive(env->outer(), stack_height); |
69 for (Environment::ShallowIterator it(env); !it.Done(); it.Advance()) { | 66 for (Environment::ShallowIterator it(env); !it.Done(); it.Advance()) { |
70 if (it.CurrentLocation().IsInvalid() && | 67 if (it.CurrentLocation().IsInvalid() && |
(...skipping 18 matching lines...) Expand all Loading... |
89 | 86 |
90 | 87 |
91 FlowGraphCompiler::FlowGraphCompiler( | 88 FlowGraphCompiler::FlowGraphCompiler( |
92 Assembler* assembler, | 89 Assembler* assembler, |
93 FlowGraph* flow_graph, | 90 FlowGraph* flow_graph, |
94 const ParsedFunction& parsed_function, | 91 const ParsedFunction& parsed_function, |
95 bool is_optimizing, | 92 bool is_optimizing, |
96 const GrowableArray<const Function*>& inline_id_to_function, | 93 const GrowableArray<const Function*>& inline_id_to_function, |
97 const GrowableArray<intptr_t>& caller_inline_id) | 94 const GrowableArray<intptr_t>& caller_inline_id) |
98 : isolate_(Isolate::Current()), | 95 : isolate_(Isolate::Current()), |
| 96 zone_(Thread::Current()->zone()), |
99 assembler_(assembler), | 97 assembler_(assembler), |
100 parsed_function_(parsed_function), | 98 parsed_function_(parsed_function), |
101 flow_graph_(*flow_graph), | 99 flow_graph_(*flow_graph), |
102 block_order_(*flow_graph->CodegenBlockOrder(is_optimizing)), | 100 block_order_(*flow_graph->CodegenBlockOrder(is_optimizing)), |
103 current_block_(NULL), | 101 current_block_(NULL), |
104 exception_handlers_list_(NULL), | 102 exception_handlers_list_(NULL), |
105 pc_descriptors_list_(NULL), | 103 pc_descriptors_list_(NULL), |
106 stackmap_table_builder_(NULL), | 104 stackmap_table_builder_(NULL), |
107 block_info_(block_order_.length()), | 105 block_info_(block_order_.length()), |
108 deopt_infos_(), | 106 deopt_infos_(), |
(...skipping 21 matching lines...) Expand all Loading... |
130 patch_code_pc_offset_(Code::kInvalidPc), | 128 patch_code_pc_offset_(Code::kInvalidPc), |
131 lazy_deopt_pc_offset_(Code::kInvalidPc), | 129 lazy_deopt_pc_offset_(Code::kInvalidPc), |
132 deopt_id_to_ic_data_(NULL), | 130 deopt_id_to_ic_data_(NULL), |
133 inlined_code_intervals_(NULL), | 131 inlined_code_intervals_(NULL), |
134 inline_id_to_function_(inline_id_to_function), | 132 inline_id_to_function_(inline_id_to_function), |
135 caller_inline_id_(caller_inline_id) { | 133 caller_inline_id_(caller_inline_id) { |
136 ASSERT(flow_graph->parsed_function().function().raw() == | 134 ASSERT(flow_graph->parsed_function().function().raw() == |
137 parsed_function.function().raw()); | 135 parsed_function.function().raw()); |
138 if (!is_optimizing) { | 136 if (!is_optimizing) { |
139 const intptr_t len = isolate()->deopt_id(); | 137 const intptr_t len = isolate()->deopt_id(); |
140 deopt_id_to_ic_data_ = new(isolate()) ZoneGrowableArray<const ICData*>(len); | 138 deopt_id_to_ic_data_ = new(zone()) ZoneGrowableArray<const ICData*>(len); |
141 deopt_id_to_ic_data_->SetLength(len); | 139 deopt_id_to_ic_data_->SetLength(len); |
142 for (intptr_t i = 0; i < len; i++) { | 140 for (intptr_t i = 0; i < len; i++) { |
143 (*deopt_id_to_ic_data_)[i] = NULL; | 141 (*deopt_id_to_ic_data_)[i] = NULL; |
144 } | 142 } |
145 const Array& old_saved_icdata = Array::Handle(isolate(), | 143 const Array& old_saved_icdata = Array::Handle(zone(), |
146 flow_graph->function().ic_data_array()); | 144 flow_graph->function().ic_data_array()); |
147 const intptr_t saved_len = | 145 const intptr_t saved_len = |
148 old_saved_icdata.IsNull() ? 0 : old_saved_icdata.Length(); | 146 old_saved_icdata.IsNull() ? 0 : old_saved_icdata.Length(); |
149 for (intptr_t i = 0; i < saved_len; i++) { | 147 for (intptr_t i = 0; i < saved_len; i++) { |
150 ICData& icd = ICData::ZoneHandle(isolate()); | 148 ICData& icd = ICData::ZoneHandle(zone()); |
151 icd ^= old_saved_icdata.At(i); | 149 icd ^= old_saved_icdata.At(i); |
152 (*deopt_id_to_ic_data_)[icd.deopt_id()] = &icd; | 150 (*deopt_id_to_ic_data_)[icd.deopt_id()] = &icd; |
153 } | 151 } |
154 } | 152 } |
155 ASSERT(assembler != NULL); | 153 ASSERT(assembler != NULL); |
156 ASSERT(!list_class_.IsNull()); | 154 ASSERT(!list_class_.IsNull()); |
157 } | 155 } |
158 | 156 |
159 | 157 |
160 void FlowGraphCompiler::InitCompiler() { | 158 void FlowGraphCompiler::InitCompiler() { |
(...skipping 598 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
759 // FlowGraphCompiler::SaveLiveRegisters | 757 // FlowGraphCompiler::SaveLiveRegisters |
760 // MaterializeObjectInstr::RemapRegisters | 758 // MaterializeObjectInstr::RemapRegisters |
761 // | 759 // |
762 Environment* FlowGraphCompiler::SlowPathEnvironmentFor( | 760 Environment* FlowGraphCompiler::SlowPathEnvironmentFor( |
763 Instruction* instruction) { | 761 Instruction* instruction) { |
764 if (instruction->env() == NULL) { | 762 if (instruction->env() == NULL) { |
765 ASSERT(!is_optimizing()); | 763 ASSERT(!is_optimizing()); |
766 return NULL; | 764 return NULL; |
767 } | 765 } |
768 | 766 |
769 Environment* env = instruction->env()->DeepCopy(isolate()); | 767 Environment* env = instruction->env()->DeepCopy(zone()); |
770 // 1. Iterate the registers in the order they will be spilled to compute | 768 // 1. Iterate the registers in the order they will be spilled to compute |
771 // the slots they will be spilled to. | 769 // the slots they will be spilled to. |
772 intptr_t next_slot = StackSize() + env->CountArgsPushed(); | 770 intptr_t next_slot = StackSize() + env->CountArgsPushed(); |
773 RegisterSet* regs = instruction->locs()->live_registers(); | 771 RegisterSet* regs = instruction->locs()->live_registers(); |
774 intptr_t fpu_reg_slots[kNumberOfFpuRegisters]; | 772 intptr_t fpu_reg_slots[kNumberOfFpuRegisters]; |
775 intptr_t cpu_reg_slots[kNumberOfCpuRegisters]; | 773 intptr_t cpu_reg_slots[kNumberOfCpuRegisters]; |
776 const intptr_t kFpuRegisterSpillFactor = kFpuRegisterSize / kWordSize; | 774 const intptr_t kFpuRegisterSpillFactor = kFpuRegisterSize / kWordSize; |
777 // FPU registers are spilled first from highest to lowest register number. | 775 // FPU registers are spilled first from highest to lowest register number. |
778 for (intptr_t i = kNumberOfFpuRegisters - 1; i >= 0; --i) { | 776 for (intptr_t i = kNumberOfFpuRegisters - 1; i >= 0; --i) { |
779 FpuRegister reg = static_cast<FpuRegister>(i); | 777 FpuRegister reg = static_cast<FpuRegister>(i); |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
847 code.set_lazy_deopt_pc_offset(lazy_deopt_pc_offset_); | 845 code.set_lazy_deopt_pc_offset(lazy_deopt_pc_offset_); |
848 } | 846 } |
849 | 847 |
850 | 848 |
851 void FlowGraphCompiler::FinalizeDeoptInfo(const Code& code) { | 849 void FlowGraphCompiler::FinalizeDeoptInfo(const Code& code) { |
852 // For functions with optional arguments, all incoming arguments are copied | 850 // For functions with optional arguments, all incoming arguments are copied |
853 // to spill slots. The deoptimization environment does not track them. | 851 // to spill slots. The deoptimization environment does not track them. |
854 const Function& function = parsed_function().function(); | 852 const Function& function = parsed_function().function(); |
855 const intptr_t incoming_arg_count = | 853 const intptr_t incoming_arg_count = |
856 function.HasOptionalParameters() ? 0 : function.num_fixed_parameters(); | 854 function.HasOptionalParameters() ? 0 : function.num_fixed_parameters(); |
857 DeoptInfoBuilder builder(isolate(), incoming_arg_count); | 855 DeoptInfoBuilder builder(zone(), incoming_arg_count); |
858 | 856 |
859 intptr_t deopt_info_table_size = DeoptTable::SizeFor(deopt_infos_.length()); | 857 intptr_t deopt_info_table_size = DeoptTable::SizeFor(deopt_infos_.length()); |
860 if (deopt_info_table_size == 0) { | 858 if (deopt_info_table_size == 0) { |
861 code.set_deopt_info_array(Object::empty_array()); | 859 code.set_deopt_info_array(Object::empty_array()); |
862 code.set_object_table(Object::empty_array()); | 860 code.set_object_table(Object::empty_array()); |
863 } else { | 861 } else { |
864 const Array& array = | 862 const Array& array = |
865 Array::Handle(Array::New(deopt_info_table_size, Heap::kOld)); | 863 Array::Handle(Array::New(deopt_info_table_size, Heap::kOld)); |
866 Smi& offset = Smi::Handle(); | 864 Smi& offset = Smi::Handle(); |
867 DeoptInfo& info = DeoptInfo::Handle(); | 865 DeoptInfo& info = DeoptInfo::Handle(); |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
921 code.set_static_calls_target_table( | 919 code.set_static_calls_target_table( |
922 Array::Handle(Array::MakeArray(static_calls_target_table_))); | 920 Array::Handle(Array::MakeArray(static_calls_target_table_))); |
923 } | 921 } |
924 | 922 |
925 | 923 |
926 // Returns 'true' if code generation for this function is complete, i.e., | 924 // Returns 'true' if code generation for this function is complete, i.e., |
927 // no fall-through to regular code is needed. | 925 // no fall-through to regular code is needed. |
928 void FlowGraphCompiler::TryIntrinsify() { | 926 void FlowGraphCompiler::TryIntrinsify() { |
929 // Intrinsification skips arguments checks, therefore disable if in checked | 927 // Intrinsification skips arguments checks, therefore disable if in checked |
930 // mode. | 928 // mode. |
931 if (FLAG_intrinsify && !I->TypeChecksEnabled()) { | 929 if (FLAG_intrinsify && !isolate()->TypeChecksEnabled()) { |
932 if (parsed_function().function().kind() == RawFunction::kImplicitGetter) { | 930 if (parsed_function().function().kind() == RawFunction::kImplicitGetter) { |
933 // An implicit getter must have a specific AST structure. | 931 // An implicit getter must have a specific AST structure. |
934 const SequenceNode& sequence_node = *parsed_function().node_sequence(); | 932 const SequenceNode& sequence_node = *parsed_function().node_sequence(); |
935 ASSERT(sequence_node.length() == 1); | 933 ASSERT(sequence_node.length() == 1); |
936 ASSERT(sequence_node.NodeAt(0)->IsReturnNode()); | 934 ASSERT(sequence_node.NodeAt(0)->IsReturnNode()); |
937 const ReturnNode& return_node = *sequence_node.NodeAt(0)->AsReturnNode(); | 935 const ReturnNode& return_node = *sequence_node.NodeAt(0)->AsReturnNode(); |
938 ASSERT(return_node.value()->IsLoadInstanceFieldNode()); | 936 ASSERT(return_node.value()->IsLoadInstanceFieldNode()); |
939 const LoadInstanceFieldNode& load_node = | 937 const LoadInstanceFieldNode& load_node = |
940 *return_node.value()->AsLoadInstanceFieldNode(); | 938 *return_node.value()->AsLoadInstanceFieldNode(); |
941 // Only intrinsify getter if the field cannot contain a mutable double. | 939 // Only intrinsify getter if the field cannot contain a mutable double. |
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1148 } | 1146 } |
1149 } | 1147 } |
1150 UNREACHABLE(); | 1148 UNREACHABLE(); |
1151 return kNoRegister; | 1149 return kNoRegister; |
1152 } | 1150 } |
1153 | 1151 |
1154 | 1152 |
1155 void FlowGraphCompiler::AllocateRegistersLocally(Instruction* instr) { | 1153 void FlowGraphCompiler::AllocateRegistersLocally(Instruction* instr) { |
1156 ASSERT(!is_optimizing()); | 1154 ASSERT(!is_optimizing()); |
1157 | 1155 |
1158 instr->InitializeLocationSummary(I->current_zone(), | 1156 instr->InitializeLocationSummary(zone(), |
1159 false); // Not optimizing. | 1157 false); // Not optimizing. |
1160 LocationSummary* locs = instr->locs(); | 1158 LocationSummary* locs = instr->locs(); |
1161 | 1159 |
1162 bool blocked_registers[kNumberOfCpuRegisters]; | 1160 bool blocked_registers[kNumberOfCpuRegisters]; |
1163 | 1161 |
1164 // Mark all available registers free. | 1162 // Mark all available registers free. |
1165 for (intptr_t i = 0; i < kNumberOfCpuRegisters; i++) { | 1163 for (intptr_t i = 0; i < kNumberOfCpuRegisters; i++) { |
1166 blocked_registers[i] = false; | 1164 blocked_registers[i] = false; |
1167 } | 1165 } |
1168 | 1166 |
(...skipping 360 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1529 const Array& arguments_descriptor, | 1527 const Array& arguments_descriptor, |
1530 intptr_t num_args_tested) { | 1528 intptr_t num_args_tested) { |
1531 if ((deopt_id_to_ic_data_ != NULL) && | 1529 if ((deopt_id_to_ic_data_ != NULL) && |
1532 ((*deopt_id_to_ic_data_)[deopt_id] != NULL)) { | 1530 ((*deopt_id_to_ic_data_)[deopt_id] != NULL)) { |
1533 const ICData* res = (*deopt_id_to_ic_data_)[deopt_id]; | 1531 const ICData* res = (*deopt_id_to_ic_data_)[deopt_id]; |
1534 ASSERT(res->deopt_id() == deopt_id); | 1532 ASSERT(res->deopt_id() == deopt_id); |
1535 ASSERT(res->target_name() == target_name.raw()); | 1533 ASSERT(res->target_name() == target_name.raw()); |
1536 ASSERT(res->NumArgsTested() == num_args_tested); | 1534 ASSERT(res->NumArgsTested() == num_args_tested); |
1537 return res; | 1535 return res; |
1538 } | 1536 } |
1539 const ICData& ic_data = ICData::ZoneHandle(isolate(), ICData::New( | 1537 const ICData& ic_data = ICData::ZoneHandle(zone(), ICData::New( |
1540 parsed_function().function(), target_name, | 1538 parsed_function().function(), target_name, |
1541 arguments_descriptor, deopt_id, num_args_tested)); | 1539 arguments_descriptor, deopt_id, num_args_tested)); |
1542 (*deopt_id_to_ic_data_)[deopt_id] = &ic_data; | 1540 (*deopt_id_to_ic_data_)[deopt_id] = &ic_data; |
1543 return &ic_data; | 1541 return &ic_data; |
1544 } | 1542 } |
1545 | 1543 |
1546 | 1544 |
1547 const ICData* FlowGraphCompiler::GetOrAddStaticCallICData( | 1545 const ICData* FlowGraphCompiler::GetOrAddStaticCallICData( |
1548 intptr_t deopt_id, | 1546 intptr_t deopt_id, |
1549 const Function& target, | 1547 const Function& target, |
1550 const Array& arguments_descriptor, | 1548 const Array& arguments_descriptor, |
1551 intptr_t num_args_tested) { | 1549 intptr_t num_args_tested) { |
1552 if ((deopt_id_to_ic_data_ != NULL) && | 1550 if ((deopt_id_to_ic_data_ != NULL) && |
1553 ((*deopt_id_to_ic_data_)[deopt_id] != NULL)) { | 1551 ((*deopt_id_to_ic_data_)[deopt_id] != NULL)) { |
1554 const ICData* res = (*deopt_id_to_ic_data_)[deopt_id]; | 1552 const ICData* res = (*deopt_id_to_ic_data_)[deopt_id]; |
1555 ASSERT(res->deopt_id() == deopt_id); | 1553 ASSERT(res->deopt_id() == deopt_id); |
1556 ASSERT(res->target_name() == target.name()); | 1554 ASSERT(res->target_name() == target.name()); |
1557 ASSERT(res->NumArgsTested() == num_args_tested); | 1555 ASSERT(res->NumArgsTested() == num_args_tested); |
1558 return res; | 1556 return res; |
1559 } | 1557 } |
1560 const ICData& ic_data = ICData::ZoneHandle(isolate(), ICData::New( | 1558 const ICData& ic_data = ICData::ZoneHandle(zone(), ICData::New( |
1561 parsed_function().function(), String::Handle(isolate(), target.name()), | 1559 parsed_function().function(), String::Handle(zone(), target.name()), |
1562 arguments_descriptor, deopt_id, num_args_tested)); | 1560 arguments_descriptor, deopt_id, num_args_tested)); |
1563 ic_data.AddTarget(target); | 1561 ic_data.AddTarget(target); |
1564 (*deopt_id_to_ic_data_)[deopt_id] = &ic_data; | 1562 (*deopt_id_to_ic_data_)[deopt_id] = &ic_data; |
1565 return &ic_data; | 1563 return &ic_data; |
1566 } | 1564 } |
1567 | 1565 |
1568 | 1566 |
1569 intptr_t FlowGraphCompiler::GetOptimizationThreshold() const { | 1567 intptr_t FlowGraphCompiler::GetOptimizationThreshold() const { |
1570 intptr_t threshold; | 1568 intptr_t threshold; |
1571 if (is_optimizing()) { | 1569 if (is_optimizing()) { |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1682 | 1680 |
1683 | 1681 |
1684 void FlowGraphCompiler::FrameStateClear() { | 1682 void FlowGraphCompiler::FrameStateClear() { |
1685 ASSERT(!is_optimizing()); | 1683 ASSERT(!is_optimizing()); |
1686 frame_state_.TruncateTo(0); | 1684 frame_state_.TruncateTo(0); |
1687 } | 1685 } |
1688 #endif | 1686 #endif |
1689 | 1687 |
1690 | 1688 |
1691 } // namespace dart | 1689 } // namespace dart |
OLD | NEW |