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" | |
9 #include "vm/assembler.h" | |
10 #include "vm/assembler_macros.h" | |
11 #include "vm/code_descriptors.h" | |
12 #include "vm/code_generator.h" | |
13 #include "vm/intermediate_language.h" | |
14 | |
15 namespace dart { | |
16 | |
17 // Forward declarations. | |
18 class FlowGraphCompiler; | |
19 class DeoptimizationStub; | |
20 | |
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 explicit FrameRegisterAllocator(FlowGraphCompiler* compiler, | |
35 bool keep_values_in_registers) | |
srdjan
2012/06/18 16:33:20
remove explicit
Vyacheslav Egorov (Google)
2012/06/18 17:51:16
Done.
| |
36 : compiler_(compiler), | |
37 stack_(kNumberOfCpuRegisters), | |
38 registers_(), | |
39 keep_values_in_registers_(keep_values_in_registers) { | |
40 for (int i = 0; i < kNumberOfCpuRegisters; i++) { | |
41 registers_[i] = NULL; | |
42 } | |
43 } | |
44 | |
45 // Notify register allocator that given instruction produced a value | |
46 // in the given register. | |
47 void Push(Register reg, Instruction* val); | |
48 | |
49 // Perform a greedy local register allocation. Consider all register free. | |
50 void AllocateRegisters(Instruction* instr); | |
51 | |
52 // Spill all live registers to the stack in order from oldest to newest. | |
53 void Spill(); | |
54 | |
55 // Returns true if all live values are stored on the stack. | |
56 // Code generator expects no live values in registers at call sites and | |
57 // branches. | |
58 bool IsSpilled() const { return stack_.length() == 0; } | |
59 | |
60 // Popuplate deoptimization stub with live registers to ensure | |
61 // that they will be pushed to the stack when deoptimization happens. | |
62 void SpillInDeoptStub(DeoptimizationStub* stub); | |
63 | |
64 private: | |
65 // Pop a value from the place where it is currently stored (either register | |
66 // or top of the stack) into a given register. If value is in the register | |
67 // verify that passed use corresponds to the instruction that produced the | |
68 // value. | |
69 void Pop(Register reg, Value* use); | |
70 | |
71 // Allocate a register that is not explicitly blocked. | |
72 // Spills a value if all non-blocked registers contain values. | |
73 Register AllocateFreeRegister(bool* blocked_registers); | |
74 | |
75 // Ensure that given register is free for allocation. | |
76 void SpillRegister(Register reg); | |
77 | |
78 // Spill the oldest live value from register to the stack. | |
79 Register SpillFirst(); | |
80 | |
81 FlowGraphCompiler* compiler() { return compiler_; } | |
82 | |
83 FlowGraphCompiler* compiler_; | |
84 | |
85 // List of registers with live values in order from oldest to newest. | |
86 GrowableArray<Register> stack_; | |
87 | |
88 // Mapping between live registers and instructions that produced values | |
89 // in them. Contains NULL for registers do not have corresponding live value. | |
90 Instruction* registers_[kNumberOfCpuRegisters]; | |
srdjan
2012/06/18 16:33:20
Consider renaming registers_to_instructions_, or j
Florian Schneider
2012/06/18 16:50:55
Can it even be BindInstr*?
Vyacheslav Egorov (Google)
2012/06/18 17:51:16
Done.
Vyacheslav Egorov (Google)
2012/06/18 17:51:16
I am not sure instructions_ reflects the purpose:
| |
91 | |
92 bool keep_values_in_registers_; | |
srdjan
2012/06/18 16:33:20
const?
Vyacheslav Egorov (Google)
2012/06/18 17:51:16
Done.
Vyacheslav Egorov (Google)
2012/06/18 17:51:16
Done.
| |
93 | |
94 DISALLOW_COPY_AND_ASSIGN(FrameRegisterAllocator); | |
95 }; | |
96 | |
97 } // namespace dart | |
98 | |
8 #if defined(TARGET_ARCH_IA32) | 99 #if defined(TARGET_ARCH_IA32) |
9 #include "vm/flow_graph_compiler_ia32.h" | 100 #include "vm/flow_graph_compiler_ia32.h" |
10 #elif defined(TARGET_ARCH_X64) | 101 #elif defined(TARGET_ARCH_X64) |
11 #include "vm/flow_graph_compiler_x64.h" | 102 #include "vm/flow_graph_compiler_x64.h" |
12 #elif defined(TARGET_ARCH_ARM) | 103 #elif defined(TARGET_ARCH_ARM) |
13 #include "vm/flow_graph_compiler_arm.h" | 104 #include "vm/flow_graph_compiler_arm.h" |
14 #else | 105 #else |
15 #error Unknown architecture. | 106 #error Unknown architecture. |
16 #endif | 107 #endif |
17 | 108 |
18 #endif // VM_FLOW_GRAPH_COMPILER_H_ | 109 #endif // VM_FLOW_GRAPH_COMPILER_H_ |
OLD | NEW |