| 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 |