| 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 #ifndef VM_FLOW_GRAPH_COMPILER_H_ | 5 #ifndef VM_FLOW_GRAPH_COMPILER_H_ |
| 6 #define VM_FLOW_GRAPH_COMPILER_H_ | 6 #define VM_FLOW_GRAPH_COMPILER_H_ |
| 7 | 7 |
| 8 #include "vm/allocation.h" | 8 #include "vm/allocation.h" |
| 9 #include "vm/assembler.h" | 9 #include "vm/assembler.h" |
| 10 #include "vm/assembler_macros.h" | 10 #include "vm/assembler_macros.h" |
| 11 #include "vm/code_descriptors.h" | 11 #include "vm/code_descriptors.h" |
| 12 #include "vm/code_generator.h" | 12 #include "vm/code_generator.h" |
| 13 #include "vm/intermediate_language.h" | 13 #include "vm/intermediate_language.h" |
| 14 | 14 |
| 15 namespace dart { | 15 namespace dart { |
| 16 | 16 |
| 17 // Forward declarations. | 17 // Forward declarations. |
| 18 class FlowGraphCompiler; | 18 class FlowGraphCompiler; |
| 19 class DeoptimizationStub; | 19 class DeoptimizationStub; |
| 20 | 20 |
| 21 | 21 |
| 22 // FrameRegisterAllocator is a simple local register allocator that tries to | |
| 23 // keep values in registers by delaying pushing them to the stack after they | |
| 24 // were produced by Bind instruction. FrameRegisterAllocator relies on the | |
| 25 // fact that IR is stack based and a value produced by a bind instruction | |
| 26 // will be used only once. For the register allocator every Bind is a push and | |
| 27 // every UseVal of a bind is a pop. | |
| 28 // It can also operate in a non-optimizing mode when every value is pushed | |
| 29 // to the stack immediately after it is produced. | |
| 30 // TODO(vegorov): replace with a linear scan register allocator once SSA is | |
| 31 // available. | |
| 32 class FrameRegisterAllocator : public ValueObject { | |
| 33 public: | |
| 34 FrameRegisterAllocator(FlowGraphCompiler* compiler, | |
| 35 bool keep_values_in_registers, | |
| 36 bool is_ssa) | |
| 37 : compiler_(compiler), | |
| 38 stack_(kNumberOfCpuRegisters), | |
| 39 registers_(), | |
| 40 keep_values_in_registers_(keep_values_in_registers && !is_ssa), | |
| 41 is_ssa_(is_ssa) { | |
| 42 for (int i = 0; i < kNumberOfCpuRegisters; i++) { | |
| 43 registers_[i] = NULL; | |
| 44 } | |
| 45 } | |
| 46 | |
| 47 // Notify register allocator that given instruction produced a value | |
| 48 // in the given register. | |
| 49 void Push(Register reg, BindInstr* val); | |
| 50 | |
| 51 // Perform a greedy local register allocation. Consider all register free. | |
| 52 void AllocateRegisters(Instruction* instr); | |
| 53 | |
| 54 // Spill all live registers to the stack in order from oldest to newest. | |
| 55 void Spill(); | |
| 56 | |
| 57 // Returns true if all live values are stored on the stack. | |
| 58 // Code generator expects no live values in registers at call sites and | |
| 59 // branches. | |
| 60 bool IsSpilled() const { return stack_.is_empty(); } | |
| 61 | |
| 62 // Popuplate deoptimization stub with live registers to ensure | |
| 63 // that they will be pushed to the stack when deoptimization happens. | |
| 64 void SpillInDeoptStub(DeoptimizationStub* stub); | |
| 65 | |
| 66 private: | |
| 67 // Pop a value from the place where it is currently stored (either register | |
| 68 // or top of the stack) into a given register. If value is in the register | |
| 69 // verify that passed use corresponds to the instruction that produced the | |
| 70 // value. | |
| 71 void Pop(Register reg, Value* use); | |
| 72 | |
| 73 // Allocate a register that is not explicitly blocked. | |
| 74 // Spills a value if all non-blocked registers contain values. | |
| 75 Register AllocateFreeRegister(bool* blocked_registers); | |
| 76 | |
| 77 // Ensure that given register is free for allocation. | |
| 78 void SpillRegister(Register reg); | |
| 79 | |
| 80 // Spill the oldest live value from register to the stack. | |
| 81 Register SpillFirst(); | |
| 82 | |
| 83 FlowGraphCompiler* compiler() { return compiler_; } | |
| 84 | |
| 85 FlowGraphCompiler* compiler_; | |
| 86 | |
| 87 // List of registers with live values in order from oldest to newest. | |
| 88 GrowableArray<Register> stack_; | |
| 89 | |
| 90 // Mapping between live registers and instructions that produced values | |
| 91 // in them. Contains NULL for registers do not have corresponding live value. | |
| 92 BindInstr* registers_[kNumberOfCpuRegisters]; | |
| 93 | |
| 94 const bool keep_values_in_registers_; | |
| 95 const bool is_ssa_; | |
| 96 | |
| 97 DISALLOW_COPY_AND_ASSIGN(FrameRegisterAllocator); | |
| 98 }; | |
| 99 | |
| 100 | |
| 101 class ParallelMoveResolver : public ValueObject { | 22 class ParallelMoveResolver : public ValueObject { |
| 102 public: | 23 public: |
| 103 explicit ParallelMoveResolver(FlowGraphCompiler* compiler); | 24 explicit ParallelMoveResolver(FlowGraphCompiler* compiler); |
| 104 | 25 |
| 105 // Resolve a set of parallel moves, emitting assembler instructions. | 26 // Resolve a set of parallel moves, emitting assembler instructions. |
| 106 void EmitNativeCode(ParallelMoveInstr* parallel_move); | 27 void EmitNativeCode(ParallelMoveInstr* parallel_move); |
| 107 | 28 |
| 108 private: | 29 private: |
| 109 // Build the initial list of moves. | 30 // Build the initial list of moves. |
| 110 void BuildInitialMoveList(ParallelMoveInstr* parallel_move); | 31 void BuildInitialMoveList(ParallelMoveInstr* parallel_move); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 138 | 59 |
| 139 | 60 |
| 140 class DeoptimizationStub : public ZoneAllocated { | 61 class DeoptimizationStub : public ZoneAllocated { |
| 141 public: | 62 public: |
| 142 DeoptimizationStub(intptr_t deopt_id, | 63 DeoptimizationStub(intptr_t deopt_id, |
| 143 intptr_t try_index, | 64 intptr_t try_index, |
| 144 DeoptReasonId reason) | 65 DeoptReasonId reason) |
| 145 : deopt_id_(deopt_id), | 66 : deopt_id_(deopt_id), |
| 146 try_index_(try_index), | 67 try_index_(try_index), |
| 147 reason_(reason), | 68 reason_(reason), |
| 148 registers_(2), | |
| 149 deoptimization_env_(NULL), | 69 deoptimization_env_(NULL), |
| 150 entry_label_() {} | 70 entry_label_() {} |
| 151 | 71 |
| 152 void Push(Register reg) { registers_.Add(reg); } | |
| 153 Label* entry_label() { return &entry_label_; } | 72 Label* entry_label() { return &entry_label_; } |
| 154 | 73 |
| 155 // Implementation is in architecture specific file. | 74 // Implementation is in architecture specific file. |
| 156 void GenerateCode(FlowGraphCompiler* compiler, intptr_t stub_ix); | 75 void GenerateCode(FlowGraphCompiler* compiler, intptr_t stub_ix); |
| 157 | 76 |
| 158 void set_deoptimization_env(Environment* env) { | 77 void set_deoptimization_env(Environment* env) { |
| 159 deoptimization_env_ = env; | 78 deoptimization_env_ = env; |
| 160 } | 79 } |
| 161 | 80 |
| 162 RawDeoptInfo* CreateDeoptInfo(FlowGraphCompiler* compiler); | 81 RawDeoptInfo* CreateDeoptInfo(FlowGraphCompiler* compiler); |
| 163 | 82 |
| 164 private: | 83 private: |
| 165 const intptr_t deopt_id_; | 84 const intptr_t deopt_id_; |
| 166 const intptr_t try_index_; | 85 const intptr_t try_index_; |
| 167 const DeoptReasonId reason_; | 86 const DeoptReasonId reason_; |
| 168 GrowableArray<Register> registers_; | |
| 169 const Environment* deoptimization_env_; | 87 const Environment* deoptimization_env_; |
| 170 Label entry_label_; | 88 Label entry_label_; |
| 171 | 89 |
| 172 DISALLOW_COPY_AND_ASSIGN(DeoptimizationStub); | 90 DISALLOW_COPY_AND_ASSIGN(DeoptimizationStub); |
| 173 }; | 91 }; |
| 174 | 92 |
| 175 | 93 |
| 176 class SlowPathCode : public ZoneAllocated { | 94 class SlowPathCode : public ZoneAllocated { |
| 177 public: | 95 public: |
| 178 SlowPathCode() : entry_label_(), exit_label_() { } | 96 SlowPathCode() : entry_label_(), exit_label_() { } |
| (...skipping 17 matching lines...) Expand all Loading... |
| 196 #include "vm/flow_graph_compiler_ia32.h" | 114 #include "vm/flow_graph_compiler_ia32.h" |
| 197 #elif defined(TARGET_ARCH_X64) | 115 #elif defined(TARGET_ARCH_X64) |
| 198 #include "vm/flow_graph_compiler_x64.h" | 116 #include "vm/flow_graph_compiler_x64.h" |
| 199 #elif defined(TARGET_ARCH_ARM) | 117 #elif defined(TARGET_ARCH_ARM) |
| 200 #include "vm/flow_graph_compiler_arm.h" | 118 #include "vm/flow_graph_compiler_arm.h" |
| 201 #else | 119 #else |
| 202 #error Unknown architecture. | 120 #error Unknown architecture. |
| 203 #endif | 121 #endif |
| 204 | 122 |
| 205 #endif // VM_FLOW_GRAPH_COMPILER_H_ | 123 #endif // VM_FLOW_GRAPH_COMPILER_H_ |
| OLD | NEW |