OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef V8_COMPILER_INSTRUCTION_SELECTOR_IMPL_H_ | 5 #ifndef V8_COMPILER_INSTRUCTION_SELECTOR_IMPL_H_ |
6 #define V8_COMPILER_INSTRUCTION_SELECTOR_IMPL_H_ | 6 #define V8_COMPILER_INSTRUCTION_SELECTOR_IMPL_H_ |
7 | 7 |
8 #include "src/compiler/instruction.h" | 8 #include "src/compiler/instruction.h" |
9 #include "src/compiler/instruction-selector.h" | 9 #include "src/compiler/instruction-selector.h" |
10 #include "src/compiler/linkage.h" | 10 #include "src/compiler/linkage.h" |
11 #include "src/macro-assembler.h" | 11 #include "src/macro-assembler.h" |
12 | 12 |
13 namespace v8 { | 13 namespace v8 { |
14 namespace internal { | 14 namespace internal { |
15 namespace compiler { | 15 namespace compiler { |
16 | 16 |
17 // A helper class for the instruction selector that simplifies construction of | 17 // A helper class for the instruction selector that simplifies construction of |
18 // Operands. This class implements a base for architecture-specific helpers. | 18 // Operands. This class implements a base for architecture-specific helpers. |
19 class OperandGenerator { | 19 class OperandGenerator { |
20 public: | 20 public: |
21 explicit OperandGenerator(InstructionSelector* selector) | 21 explicit OperandGenerator(InstructionSelector* selector) |
22 : selector_(selector) {} | 22 : selector_(selector) {} |
23 | 23 |
24 InstructionOperand* DefineAsRegister(Node* node) { | 24 InstructionOperand* DefineAsRegister(Node* node) { |
25 return Define(node, new (zone()) | 25 return Define(node, |
26 UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER)); | 26 new (zone()) UnallocatedOperand( |
| 27 UnallocatedOperand::MUST_HAVE_REGISTER, GetVReg(node))); |
27 } | 28 } |
28 | 29 |
29 InstructionOperand* DefineSameAsFirst(Node* result) { | 30 InstructionOperand* DefineSameAsFirst(Node* node) { |
30 return Define(result, new (zone()) | 31 return Define(node, |
31 UnallocatedOperand(UnallocatedOperand::SAME_AS_FIRST_INPUT)); | 32 new (zone()) UnallocatedOperand( |
| 33 UnallocatedOperand::SAME_AS_FIRST_INPUT, GetVReg(node))); |
32 } | 34 } |
33 | 35 |
34 InstructionOperand* DefineAsFixed(Node* node, Register reg) { | 36 InstructionOperand* DefineAsFixed(Node* node, Register reg) { |
35 return Define(node, new (zone()) | 37 return Define(node, new (zone()) UnallocatedOperand( |
36 UnallocatedOperand(UnallocatedOperand::FIXED_REGISTER, | 38 UnallocatedOperand::FIXED_REGISTER, |
37 Register::ToAllocationIndex(reg))); | 39 Register::ToAllocationIndex(reg), GetVReg(node))); |
38 } | 40 } |
39 | 41 |
40 InstructionOperand* DefineAsFixed(Node* node, DoubleRegister reg) { | 42 InstructionOperand* DefineAsFixed(Node* node, DoubleRegister reg) { |
41 return Define(node, new (zone()) | 43 return Define(node, |
42 UnallocatedOperand(UnallocatedOperand::FIXED_DOUBLE_REGISTER, | 44 new (zone()) UnallocatedOperand( |
43 DoubleRegister::ToAllocationIndex(reg))); | 45 UnallocatedOperand::FIXED_DOUBLE_REGISTER, |
| 46 DoubleRegister::ToAllocationIndex(reg), GetVReg(node))); |
44 } | 47 } |
45 | 48 |
46 InstructionOperand* DefineAsConstant(Node* node) { | 49 InstructionOperand* DefineAsConstant(Node* node) { |
47 selector()->MarkAsDefined(node); | 50 selector()->MarkAsDefined(node); |
48 int virtual_register = selector_->GetVirtualRegister(node); | 51 int virtual_register = GetVReg(node); |
49 sequence()->AddConstant(virtual_register, ToConstant(node)); | 52 sequence()->AddConstant(virtual_register, ToConstant(node)); |
50 return ConstantOperand::Create(virtual_register, zone()); | 53 return ConstantOperand::Create(virtual_register, zone()); |
51 } | 54 } |
52 | 55 |
53 InstructionOperand* DefineAsLocation(Node* node, LinkageLocation location, | 56 InstructionOperand* DefineAsLocation(Node* node, LinkageLocation location, |
54 MachineType type) { | 57 MachineType type) { |
55 return Define(node, ToUnallocatedOperand(location, type)); | 58 return Define(node, ToUnallocatedOperand(location, type, GetVReg(node))); |
56 } | 59 } |
57 | 60 |
58 InstructionOperand* Use(Node* node) { | 61 InstructionOperand* Use(Node* node) { |
59 return Use( | 62 return Use(node, new (zone()) UnallocatedOperand( |
60 node, new (zone()) UnallocatedOperand( | 63 UnallocatedOperand::NONE, |
61 UnallocatedOperand::NONE, UnallocatedOperand::USED_AT_START)); | 64 UnallocatedOperand::USED_AT_START, GetVReg(node))); |
62 } | 65 } |
63 | 66 |
64 InstructionOperand* UseRegister(Node* node) { | 67 InstructionOperand* UseRegister(Node* node) { |
65 return Use(node, new (zone()) | 68 return Use(node, new (zone()) UnallocatedOperand( |
66 UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER, | 69 UnallocatedOperand::MUST_HAVE_REGISTER, |
67 UnallocatedOperand::USED_AT_START)); | 70 UnallocatedOperand::USED_AT_START, GetVReg(node))); |
68 } | 71 } |
69 | 72 |
70 // Use register or operand for the node. If a register is chosen, it won't | 73 // Use register or operand for the node. If a register is chosen, it won't |
71 // alias any temporary or output registers. | 74 // alias any temporary or output registers. |
72 InstructionOperand* UseUnique(Node* node) { | 75 InstructionOperand* UseUnique(Node* node) { |
73 return Use(node, new (zone()) UnallocatedOperand(UnallocatedOperand::NONE)); | 76 return Use(node, new (zone()) UnallocatedOperand(UnallocatedOperand::NONE, |
| 77 GetVReg(node))); |
74 } | 78 } |
75 | 79 |
76 // Use a unique register for the node that does not alias any temporary or | 80 // Use a unique register for the node that does not alias any temporary or |
77 // output registers. | 81 // output registers. |
78 InstructionOperand* UseUniqueRegister(Node* node) { | 82 InstructionOperand* UseUniqueRegister(Node* node) { |
79 return Use(node, new (zone()) | 83 return Use(node, |
80 UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER)); | 84 new (zone()) UnallocatedOperand( |
| 85 UnallocatedOperand::MUST_HAVE_REGISTER, GetVReg(node))); |
81 } | 86 } |
82 | 87 |
83 InstructionOperand* UseFixed(Node* node, Register reg) { | 88 InstructionOperand* UseFixed(Node* node, Register reg) { |
84 return Use(node, new (zone()) | 89 return Use(node, new (zone()) UnallocatedOperand( |
85 UnallocatedOperand(UnallocatedOperand::FIXED_REGISTER, | 90 UnallocatedOperand::FIXED_REGISTER, |
86 Register::ToAllocationIndex(reg))); | 91 Register::ToAllocationIndex(reg), GetVReg(node))); |
87 } | 92 } |
88 | 93 |
89 InstructionOperand* UseFixed(Node* node, DoubleRegister reg) { | 94 InstructionOperand* UseFixed(Node* node, DoubleRegister reg) { |
90 return Use(node, new (zone()) | 95 return Use(node, |
91 UnallocatedOperand(UnallocatedOperand::FIXED_DOUBLE_REGISTER, | 96 new (zone()) UnallocatedOperand( |
92 DoubleRegister::ToAllocationIndex(reg))); | 97 UnallocatedOperand::FIXED_DOUBLE_REGISTER, |
| 98 DoubleRegister::ToAllocationIndex(reg), GetVReg(node))); |
93 } | 99 } |
94 | 100 |
95 InstructionOperand* UseImmediate(Node* node) { | 101 InstructionOperand* UseImmediate(Node* node) { |
96 int index = sequence()->AddImmediate(ToConstant(node)); | 102 int index = sequence()->AddImmediate(ToConstant(node)); |
97 return ImmediateOperand::Create(index, zone()); | 103 return ImmediateOperand::Create(index, zone()); |
98 } | 104 } |
99 | 105 |
100 InstructionOperand* UseLocation(Node* node, LinkageLocation location, | 106 InstructionOperand* UseLocation(Node* node, LinkageLocation location, |
101 MachineType type) { | 107 MachineType type) { |
102 return Use(node, ToUnallocatedOperand(location, type)); | 108 return Use(node, ToUnallocatedOperand(location, type, GetVReg(node))); |
103 } | 109 } |
104 | 110 |
105 InstructionOperand* TempRegister() { | 111 InstructionOperand* TempRegister() { |
106 UnallocatedOperand* op = | 112 return new (zone()) UnallocatedOperand( |
107 new (zone()) UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER, | 113 UnallocatedOperand::MUST_HAVE_REGISTER, |
108 UnallocatedOperand::USED_AT_START); | 114 UnallocatedOperand::USED_AT_START, sequence()->NextVirtualRegister()); |
109 op->set_virtual_register(sequence()->NextVirtualRegister()); | |
110 return op; | |
111 } | 115 } |
112 | 116 |
113 InstructionOperand* TempDoubleRegister() { | 117 InstructionOperand* TempDoubleRegister() { |
114 UnallocatedOperand* op = | 118 UnallocatedOperand* op = new (zone()) UnallocatedOperand( |
115 new (zone()) UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER, | 119 UnallocatedOperand::MUST_HAVE_REGISTER, |
116 UnallocatedOperand::USED_AT_START); | 120 UnallocatedOperand::USED_AT_START, sequence()->NextVirtualRegister()); |
117 op->set_virtual_register(sequence()->NextVirtualRegister()); | |
118 sequence()->MarkAsDouble(op->virtual_register()); | 121 sequence()->MarkAsDouble(op->virtual_register()); |
119 return op; | 122 return op; |
120 } | 123 } |
121 | 124 |
122 InstructionOperand* TempRegister(Register reg) { | 125 InstructionOperand* TempRegister(Register reg) { |
123 return new (zone()) UnallocatedOperand(UnallocatedOperand::FIXED_REGISTER, | 126 return new (zone()) UnallocatedOperand( |
124 Register::ToAllocationIndex(reg)); | 127 UnallocatedOperand::FIXED_REGISTER, Register::ToAllocationIndex(reg), |
| 128 UnallocatedOperand::kInvalidVirtualRegister); |
125 } | 129 } |
126 | 130 |
127 InstructionOperand* TempImmediate(int32_t imm) { | 131 InstructionOperand* TempImmediate(int32_t imm) { |
128 int index = sequence()->AddImmediate(Constant(imm)); | 132 int index = sequence()->AddImmediate(Constant(imm)); |
129 return ImmediateOperand::Create(index, zone()); | 133 return ImmediateOperand::Create(index, zone()); |
130 } | 134 } |
131 | 135 |
132 InstructionOperand* TempLocation(LinkageLocation location, MachineType type) { | 136 InstructionOperand* TempLocation(LinkageLocation location, MachineType type) { |
133 UnallocatedOperand* op = ToUnallocatedOperand(location, type); | 137 return ToUnallocatedOperand(location, type, |
134 op->set_virtual_register(sequence()->NextVirtualRegister()); | 138 sequence()->NextVirtualRegister()); |
135 return op; | |
136 } | 139 } |
137 | 140 |
138 InstructionOperand* Label(BasicBlock* block) { | 141 InstructionOperand* Label(BasicBlock* block) { |
139 int index = sequence()->AddImmediate(Constant(block->GetRpoNumber())); | 142 int index = sequence()->AddImmediate(Constant(block->GetRpoNumber())); |
140 return ImmediateOperand::Create(index, zone()); | 143 return ImmediateOperand::Create(index, zone()); |
141 } | 144 } |
142 | 145 |
143 protected: | 146 protected: |
144 InstructionSelector* selector() const { return selector_; } | 147 InstructionSelector* selector() const { return selector_; } |
145 InstructionSequence* sequence() const { return selector()->sequence(); } | 148 InstructionSequence* sequence() const { return selector()->sequence(); } |
146 Zone* zone() const { return selector()->instruction_zone(); } | 149 Zone* zone() const { return selector()->instruction_zone(); } |
147 | 150 |
148 private: | 151 private: |
| 152 int GetVReg(Node* node) const { return selector_->GetVirtualRegister(node); } |
| 153 |
149 static Constant ToConstant(const Node* node) { | 154 static Constant ToConstant(const Node* node) { |
150 switch (node->opcode()) { | 155 switch (node->opcode()) { |
151 case IrOpcode::kInt32Constant: | 156 case IrOpcode::kInt32Constant: |
152 return Constant(OpParameter<int32_t>(node)); | 157 return Constant(OpParameter<int32_t>(node)); |
153 case IrOpcode::kInt64Constant: | 158 case IrOpcode::kInt64Constant: |
154 return Constant(OpParameter<int64_t>(node)); | 159 return Constant(OpParameter<int64_t>(node)); |
155 case IrOpcode::kFloat32Constant: | 160 case IrOpcode::kFloat32Constant: |
156 return Constant(OpParameter<float>(node)); | 161 return Constant(OpParameter<float>(node)); |
157 case IrOpcode::kFloat64Constant: | 162 case IrOpcode::kFloat64Constant: |
158 case IrOpcode::kNumberConstant: | 163 case IrOpcode::kNumberConstant: |
159 return Constant(OpParameter<double>(node)); | 164 return Constant(OpParameter<double>(node)); |
160 case IrOpcode::kExternalConstant: | 165 case IrOpcode::kExternalConstant: |
161 return Constant(OpParameter<ExternalReference>(node)); | 166 return Constant(OpParameter<ExternalReference>(node)); |
162 case IrOpcode::kHeapConstant: | 167 case IrOpcode::kHeapConstant: |
163 return Constant(OpParameter<Unique<HeapObject> >(node).handle()); | 168 return Constant(OpParameter<Unique<HeapObject> >(node).handle()); |
164 default: | 169 default: |
165 break; | 170 break; |
166 } | 171 } |
167 UNREACHABLE(); | 172 UNREACHABLE(); |
168 return Constant(static_cast<int32_t>(0)); | 173 return Constant(static_cast<int32_t>(0)); |
169 } | 174 } |
170 | 175 |
171 UnallocatedOperand* Define(Node* node, UnallocatedOperand* operand) { | 176 UnallocatedOperand* Define(Node* node, UnallocatedOperand* operand) { |
172 DCHECK_NOT_NULL(node); | 177 DCHECK_NOT_NULL(node); |
173 DCHECK_NOT_NULL(operand); | 178 DCHECK_NOT_NULL(operand); |
174 operand->set_virtual_register(selector_->GetVirtualRegister(node)); | 179 DCHECK_EQ(operand->virtual_register(), GetVReg(node)); |
175 selector()->MarkAsDefined(node); | 180 selector()->MarkAsDefined(node); |
176 return operand; | 181 return operand; |
177 } | 182 } |
178 | 183 |
179 UnallocatedOperand* Use(Node* node, UnallocatedOperand* operand) { | 184 UnallocatedOperand* Use(Node* node, UnallocatedOperand* operand) { |
180 DCHECK_NOT_NULL(node); | 185 DCHECK_NOT_NULL(node); |
181 DCHECK_NOT_NULL(operand); | 186 DCHECK_NOT_NULL(operand); |
182 operand->set_virtual_register(selector_->GetVirtualRegister(node)); | 187 DCHECK_EQ(operand->virtual_register(), GetVReg(node)); |
183 selector()->MarkAsUsed(node); | 188 selector()->MarkAsUsed(node); |
184 return operand; | 189 return operand; |
185 } | 190 } |
186 | 191 |
187 UnallocatedOperand* ToUnallocatedOperand(LinkageLocation location, | 192 UnallocatedOperand* ToUnallocatedOperand(LinkageLocation location, |
188 MachineType type) { | 193 MachineType type, |
| 194 int virtual_register) { |
189 if (location.location_ == LinkageLocation::ANY_REGISTER) { | 195 if (location.location_ == LinkageLocation::ANY_REGISTER) { |
190 // any machine register. | 196 // any machine register. |
191 return new (zone()) | 197 return new (zone()) UnallocatedOperand( |
192 UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER); | 198 UnallocatedOperand::MUST_HAVE_REGISTER, virtual_register); |
193 } | 199 } |
194 if (location.location_ < 0) { | 200 if (location.location_ < 0) { |
195 // a location on the caller frame. | 201 // a location on the caller frame. |
196 return new (zone()) UnallocatedOperand(UnallocatedOperand::FIXED_SLOT, | 202 return new (zone()) UnallocatedOperand( |
197 location.location_); | 203 UnallocatedOperand::FIXED_SLOT, location.location_, virtual_register); |
198 } | 204 } |
199 if (location.location_ > LinkageLocation::ANY_REGISTER) { | 205 if (location.location_ > LinkageLocation::ANY_REGISTER) { |
200 // a spill location on this (callee) frame. | 206 // a spill location on this (callee) frame. |
201 return new (zone()) UnallocatedOperand( | 207 return new (zone()) UnallocatedOperand( |
202 UnallocatedOperand::FIXED_SLOT, | 208 UnallocatedOperand::FIXED_SLOT, |
203 location.location_ - LinkageLocation::ANY_REGISTER - 1); | 209 location.location_ - LinkageLocation::ANY_REGISTER - 1, |
| 210 virtual_register); |
204 } | 211 } |
205 // a fixed register. | 212 // a fixed register. |
206 if (RepresentationOf(type) == kRepFloat64) { | 213 if (RepresentationOf(type) == kRepFloat64) { |
207 return new (zone()) UnallocatedOperand( | 214 return new (zone()) |
208 UnallocatedOperand::FIXED_DOUBLE_REGISTER, location.location_); | 215 UnallocatedOperand(UnallocatedOperand::FIXED_DOUBLE_REGISTER, |
| 216 location.location_, virtual_register); |
209 } | 217 } |
210 return new (zone()) UnallocatedOperand(UnallocatedOperand::FIXED_REGISTER, | 218 return new (zone()) |
211 location.location_); | 219 UnallocatedOperand(UnallocatedOperand::FIXED_REGISTER, |
| 220 location.location_, virtual_register); |
212 } | 221 } |
213 | 222 |
214 InstructionSelector* selector_; | 223 InstructionSelector* selector_; |
215 }; | 224 }; |
216 | 225 |
217 | 226 |
218 // The flags continuation is a way to combine a branch or a materialization | 227 // The flags continuation is a way to combine a branch or a materialization |
219 // of a boolean value with an instruction that sets the flags register. | 228 // of a boolean value with an instruction that sets the flags register. |
220 // The whole instruction is treated as a unit by the register allocator, and | 229 // The whole instruction is treated as a unit by the register allocator, and |
221 // thus no spills or moves can be introduced between the flags-setting | 230 // thus no spills or moves can be introduced between the flags-setting |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
354 : (frame_state_descriptor->GetTotalSize() + | 363 : (frame_state_descriptor->GetTotalSize() + |
355 1); // Include deopt id. | 364 1); // Include deopt id. |
356 } | 365 } |
357 }; | 366 }; |
358 | 367 |
359 } // namespace compiler | 368 } // namespace compiler |
360 } // namespace internal | 369 } // namespace internal |
361 } // namespace v8 | 370 } // namespace v8 |
362 | 371 |
363 #endif // V8_COMPILER_INSTRUCTION_SELECTOR_IMPL_H_ | 372 #endif // V8_COMPILER_INSTRUCTION_SELECTOR_IMPL_H_ |
OLD | NEW |