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 NoOutput() { |
25 return Define(node, | 25 return InstructionOperand(); // Generates an invalid operand. |
26 new (zone()) UnallocatedOperand( | |
27 UnallocatedOperand::MUST_HAVE_REGISTER, GetVReg(node))); | |
28 } | 26 } |
29 | 27 |
30 InstructionOperand* DefineSameAsFirst(Node* node) { | 28 InstructionOperand DefineAsRegister(Node* node) { |
31 return Define(node, | 29 return Define(node, |
32 new (zone()) UnallocatedOperand( | 30 UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER, |
33 UnallocatedOperand::SAME_AS_FIRST_INPUT, GetVReg(node))); | 31 GetVReg(node))); |
34 } | 32 } |
35 | 33 |
36 InstructionOperand* DefineAsFixed(Node* node, Register reg) { | 34 InstructionOperand DefineSameAsFirst(Node* node) { |
37 return Define(node, new (zone()) UnallocatedOperand( | 35 return Define(node, |
38 UnallocatedOperand::FIXED_REGISTER, | 36 UnallocatedOperand(UnallocatedOperand::SAME_AS_FIRST_INPUT, |
39 Register::ToAllocationIndex(reg), GetVReg(node))); | 37 GetVReg(node))); |
40 } | 38 } |
41 | 39 |
42 InstructionOperand* DefineAsFixed(Node* node, DoubleRegister reg) { | 40 InstructionOperand DefineAsFixed(Node* node, Register reg) { |
43 return Define(node, | 41 return Define(node, UnallocatedOperand(UnallocatedOperand::FIXED_REGISTER, |
44 new (zone()) UnallocatedOperand( | 42 Register::ToAllocationIndex(reg), |
45 UnallocatedOperand::FIXED_DOUBLE_REGISTER, | 43 GetVReg(node))); |
46 DoubleRegister::ToAllocationIndex(reg), GetVReg(node))); | |
47 } | 44 } |
48 | 45 |
49 InstructionOperand* DefineAsConstant(Node* node) { | 46 InstructionOperand DefineAsFixed(Node* node, DoubleRegister reg) { |
| 47 return Define(node, |
| 48 UnallocatedOperand(UnallocatedOperand::FIXED_DOUBLE_REGISTER, |
| 49 DoubleRegister::ToAllocationIndex(reg), |
| 50 GetVReg(node))); |
| 51 } |
| 52 |
| 53 InstructionOperand DefineAsConstant(Node* node) { |
50 selector()->MarkAsDefined(node); | 54 selector()->MarkAsDefined(node); |
51 int virtual_register = GetVReg(node); | 55 int virtual_register = GetVReg(node); |
52 sequence()->AddConstant(virtual_register, ToConstant(node)); | 56 sequence()->AddConstant(virtual_register, ToConstant(node)); |
53 return ConstantOperand::Create(virtual_register, zone()); | 57 return ConstantOperand(virtual_register); |
54 } | 58 } |
55 | 59 |
56 InstructionOperand* DefineAsLocation(Node* node, LinkageLocation location, | 60 InstructionOperand DefineAsLocation(Node* node, LinkageLocation location, |
57 MachineType type) { | 61 MachineType type) { |
58 return Define(node, ToUnallocatedOperand(location, type, GetVReg(node))); | 62 return Define(node, ToUnallocatedOperand(location, type, GetVReg(node))); |
59 } | 63 } |
60 | 64 |
61 InstructionOperand* Use(Node* node) { | 65 InstructionOperand Use(Node* node) { |
62 return Use(node, new (zone()) UnallocatedOperand( | 66 return Use(node, UnallocatedOperand(UnallocatedOperand::NONE, |
63 UnallocatedOperand::NONE, | 67 UnallocatedOperand::USED_AT_START, |
64 UnallocatedOperand::USED_AT_START, GetVReg(node))); | 68 GetVReg(node))); |
65 } | 69 } |
66 | 70 |
67 InstructionOperand* UseRegister(Node* node) { | 71 InstructionOperand UseRegister(Node* node) { |
68 return Use(node, new (zone()) UnallocatedOperand( | 72 return Use(node, UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER, |
69 UnallocatedOperand::MUST_HAVE_REGISTER, | 73 UnallocatedOperand::USED_AT_START, |
70 UnallocatedOperand::USED_AT_START, GetVReg(node))); | 74 GetVReg(node))); |
71 } | 75 } |
72 | 76 |
73 // Use register or operand for the node. If a register is chosen, it won't | 77 // Use register or operand for the node. If a register is chosen, it won't |
74 // alias any temporary or output registers. | 78 // alias any temporary or output registers. |
75 InstructionOperand* UseUnique(Node* node) { | 79 InstructionOperand UseUnique(Node* node) { |
76 return Use(node, new (zone()) UnallocatedOperand(UnallocatedOperand::NONE, | 80 return Use(node, |
77 GetVReg(node))); | 81 UnallocatedOperand(UnallocatedOperand::NONE, GetVReg(node))); |
78 } | 82 } |
79 | 83 |
80 // Use a unique register for the node that does not alias any temporary or | 84 // Use a unique register for the node that does not alias any temporary or |
81 // output registers. | 85 // output registers. |
82 InstructionOperand* UseUniqueRegister(Node* node) { | 86 InstructionOperand UseUniqueRegister(Node* node) { |
83 return Use(node, | 87 return Use(node, UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER, |
84 new (zone()) UnallocatedOperand( | 88 GetVReg(node))); |
85 UnallocatedOperand::MUST_HAVE_REGISTER, GetVReg(node))); | |
86 } | 89 } |
87 | 90 |
88 InstructionOperand* UseFixed(Node* node, Register reg) { | 91 InstructionOperand UseFixed(Node* node, Register reg) { |
89 return Use(node, new (zone()) UnallocatedOperand( | 92 return Use(node, UnallocatedOperand(UnallocatedOperand::FIXED_REGISTER, |
90 UnallocatedOperand::FIXED_REGISTER, | 93 Register::ToAllocationIndex(reg), |
91 Register::ToAllocationIndex(reg), GetVReg(node))); | 94 GetVReg(node))); |
92 } | 95 } |
93 | 96 |
94 InstructionOperand* UseFixed(Node* node, DoubleRegister reg) { | 97 InstructionOperand UseFixed(Node* node, DoubleRegister reg) { |
95 return Use(node, | 98 return Use(node, |
96 new (zone()) UnallocatedOperand( | 99 UnallocatedOperand(UnallocatedOperand::FIXED_DOUBLE_REGISTER, |
97 UnallocatedOperand::FIXED_DOUBLE_REGISTER, | 100 DoubleRegister::ToAllocationIndex(reg), |
98 DoubleRegister::ToAllocationIndex(reg), GetVReg(node))); | 101 GetVReg(node))); |
99 } | 102 } |
100 | 103 |
101 InstructionOperand* UseImmediate(Node* node) { | 104 InstructionOperand UseImmediate(Node* node) { |
102 int index = sequence()->AddImmediate(ToConstant(node)); | 105 int index = sequence()->AddImmediate(ToConstant(node)); |
103 return ImmediateOperand::Create(index, zone()); | 106 return ImmediateOperand(index); |
104 } | 107 } |
105 | 108 |
106 InstructionOperand* UseLocation(Node* node, LinkageLocation location, | 109 InstructionOperand UseLocation(Node* node, LinkageLocation location, |
107 MachineType type) { | 110 MachineType type) { |
108 return Use(node, ToUnallocatedOperand(location, type, GetVReg(node))); | 111 return Use(node, ToUnallocatedOperand(location, type, GetVReg(node))); |
109 } | 112 } |
110 | 113 |
111 InstructionOperand* TempRegister() { | 114 InstructionOperand TempRegister() { |
112 return new (zone()) UnallocatedOperand( | 115 return UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER, |
| 116 UnallocatedOperand::USED_AT_START, |
| 117 sequence()->NextVirtualRegister()); |
| 118 } |
| 119 |
| 120 InstructionOperand TempDoubleRegister() { |
| 121 UnallocatedOperand op = UnallocatedOperand( |
113 UnallocatedOperand::MUST_HAVE_REGISTER, | 122 UnallocatedOperand::MUST_HAVE_REGISTER, |
114 UnallocatedOperand::USED_AT_START, sequence()->NextVirtualRegister()); | 123 UnallocatedOperand::USED_AT_START, sequence()->NextVirtualRegister()); |
115 } | 124 sequence()->MarkAsDouble(op.virtual_register()); |
116 | |
117 InstructionOperand* TempDoubleRegister() { | |
118 UnallocatedOperand* op = new (zone()) UnallocatedOperand( | |
119 UnallocatedOperand::MUST_HAVE_REGISTER, | |
120 UnallocatedOperand::USED_AT_START, sequence()->NextVirtualRegister()); | |
121 sequence()->MarkAsDouble(op->virtual_register()); | |
122 return op; | 125 return op; |
123 } | 126 } |
124 | 127 |
125 InstructionOperand* TempRegister(Register reg) { | 128 InstructionOperand TempRegister(Register reg) { |
126 return new (zone()) UnallocatedOperand( | 129 return UnallocatedOperand(UnallocatedOperand::FIXED_REGISTER, |
127 UnallocatedOperand::FIXED_REGISTER, Register::ToAllocationIndex(reg), | 130 Register::ToAllocationIndex(reg), |
128 UnallocatedOperand::kInvalidVirtualRegister); | 131 UnallocatedOperand::kInvalidVirtualRegister); |
129 } | 132 } |
130 | 133 |
131 InstructionOperand* TempImmediate(int32_t imm) { | 134 InstructionOperand TempImmediate(int32_t imm) { |
132 int index = sequence()->AddImmediate(Constant(imm)); | 135 int index = sequence()->AddImmediate(Constant(imm)); |
133 return ImmediateOperand::Create(index, zone()); | 136 return ImmediateOperand(index); |
134 } | 137 } |
135 | 138 |
136 InstructionOperand* TempLocation(LinkageLocation location, MachineType type) { | 139 InstructionOperand TempLocation(LinkageLocation location, MachineType type) { |
137 return ToUnallocatedOperand(location, type, | 140 return ToUnallocatedOperand(location, type, |
138 sequence()->NextVirtualRegister()); | 141 sequence()->NextVirtualRegister()); |
139 } | 142 } |
140 | 143 |
141 InstructionOperand* Label(BasicBlock* block) { | 144 InstructionOperand Label(BasicBlock* block) { |
142 int index = sequence()->AddImmediate(Constant(block->GetRpoNumber())); | 145 int index = sequence()->AddImmediate(Constant(block->GetRpoNumber())); |
143 return ImmediateOperand::Create(index, zone()); | 146 return ImmediateOperand(index); |
144 } | 147 } |
145 | 148 |
146 protected: | 149 protected: |
147 InstructionSelector* selector() const { return selector_; } | 150 InstructionSelector* selector() const { return selector_; } |
148 InstructionSequence* sequence() const { return selector()->sequence(); } | 151 InstructionSequence* sequence() const { return selector()->sequence(); } |
149 Zone* zone() const { return selector()->instruction_zone(); } | 152 Zone* zone() const { return selector()->instruction_zone(); } |
150 | 153 |
151 private: | 154 private: |
152 int GetVReg(Node* node) const { return selector_->GetVirtualRegister(node); } | 155 int GetVReg(Node* node) const { return selector_->GetVirtualRegister(node); } |
153 | 156 |
(...skipping 12 matching lines...) Expand all Loading... |
166 return Constant(OpParameter<ExternalReference>(node)); | 169 return Constant(OpParameter<ExternalReference>(node)); |
167 case IrOpcode::kHeapConstant: | 170 case IrOpcode::kHeapConstant: |
168 return Constant(OpParameter<Unique<HeapObject> >(node).handle()); | 171 return Constant(OpParameter<Unique<HeapObject> >(node).handle()); |
169 default: | 172 default: |
170 break; | 173 break; |
171 } | 174 } |
172 UNREACHABLE(); | 175 UNREACHABLE(); |
173 return Constant(static_cast<int32_t>(0)); | 176 return Constant(static_cast<int32_t>(0)); |
174 } | 177 } |
175 | 178 |
176 UnallocatedOperand* Define(Node* node, UnallocatedOperand* operand) { | 179 UnallocatedOperand Define(Node* node, UnallocatedOperand operand) { |
177 DCHECK_NOT_NULL(node); | 180 DCHECK_NOT_NULL(node); |
178 DCHECK_NOT_NULL(operand); | 181 DCHECK_EQ(operand.virtual_register(), GetVReg(node)); |
179 DCHECK_EQ(operand->virtual_register(), GetVReg(node)); | |
180 selector()->MarkAsDefined(node); | 182 selector()->MarkAsDefined(node); |
181 return operand; | 183 return operand; |
182 } | 184 } |
183 | 185 |
184 UnallocatedOperand* Use(Node* node, UnallocatedOperand* operand) { | 186 UnallocatedOperand Use(Node* node, UnallocatedOperand operand) { |
185 DCHECK_NOT_NULL(node); | 187 DCHECK_NOT_NULL(node); |
186 DCHECK_NOT_NULL(operand); | 188 DCHECK_EQ(operand.virtual_register(), GetVReg(node)); |
187 DCHECK_EQ(operand->virtual_register(), GetVReg(node)); | |
188 selector()->MarkAsUsed(node); | 189 selector()->MarkAsUsed(node); |
189 return operand; | 190 return operand; |
190 } | 191 } |
191 | 192 |
192 UnallocatedOperand* ToUnallocatedOperand(LinkageLocation location, | 193 UnallocatedOperand ToUnallocatedOperand(LinkageLocation location, |
193 MachineType type, | 194 MachineType type, |
194 int virtual_register) { | 195 int virtual_register) { |
195 if (location.location_ == LinkageLocation::ANY_REGISTER) { | 196 if (location.location_ == LinkageLocation::ANY_REGISTER) { |
196 // any machine register. | 197 // any machine register. |
197 return new (zone()) UnallocatedOperand( | 198 return UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER, |
198 UnallocatedOperand::MUST_HAVE_REGISTER, virtual_register); | 199 virtual_register); |
199 } | 200 } |
200 if (location.location_ < 0) { | 201 if (location.location_ < 0) { |
201 // a location on the caller frame. | 202 // a location on the caller frame. |
202 return new (zone()) UnallocatedOperand( | 203 return UnallocatedOperand(UnallocatedOperand::FIXED_SLOT, |
203 UnallocatedOperand::FIXED_SLOT, location.location_, virtual_register); | 204 location.location_, virtual_register); |
204 } | 205 } |
205 if (location.location_ > LinkageLocation::ANY_REGISTER) { | 206 if (location.location_ > LinkageLocation::ANY_REGISTER) { |
206 // a spill location on this (callee) frame. | 207 // a spill location on this (callee) frame. |
207 return new (zone()) UnallocatedOperand( | 208 return UnallocatedOperand( |
208 UnallocatedOperand::FIXED_SLOT, | 209 UnallocatedOperand::FIXED_SLOT, |
209 location.location_ - LinkageLocation::ANY_REGISTER - 1, | 210 location.location_ - LinkageLocation::ANY_REGISTER - 1, |
210 virtual_register); | 211 virtual_register); |
211 } | 212 } |
212 // a fixed register. | 213 // a fixed register. |
213 if (RepresentationOf(type) == kRepFloat64) { | 214 if (RepresentationOf(type) == kRepFloat64) { |
214 return new (zone()) | 215 return UnallocatedOperand(UnallocatedOperand::FIXED_DOUBLE_REGISTER, |
215 UnallocatedOperand(UnallocatedOperand::FIXED_DOUBLE_REGISTER, | 216 location.location_, virtual_register); |
216 location.location_, virtual_register); | |
217 } | 217 } |
218 return new (zone()) | 218 return UnallocatedOperand(UnallocatedOperand::FIXED_REGISTER, |
219 UnallocatedOperand(UnallocatedOperand::FIXED_REGISTER, | 219 location.location_, virtual_register); |
220 location.location_, virtual_register); | |
221 } | 220 } |
222 | 221 |
223 InstructionSelector* selector_; | 222 InstructionSelector* selector_; |
224 }; | 223 }; |
225 | 224 |
226 | 225 |
227 // The flags continuation is a way to combine a branch or a materialization | 226 // The flags continuation is a way to combine a branch or a materialization |
228 // of a boolean value with an instruction that sets the flags register. | 227 // of a boolean value with an instruction that sets the flags register. |
229 // The whole instruction is treated as a unit by the register allocator, and | 228 // The whole instruction is treated as a unit by the register allocator, and |
230 // thus no spills or moves can be introduced between the flags-setting | 229 // 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... |
363 : (frame_state_descriptor->GetTotalSize() + | 362 : (frame_state_descriptor->GetTotalSize() + |
364 1); // Include deopt id. | 363 1); // Include deopt id. |
365 } | 364 } |
366 }; | 365 }; |
367 | 366 |
368 } // namespace compiler | 367 } // namespace compiler |
369 } // namespace internal | 368 } // namespace internal |
370 } // namespace v8 | 369 } // namespace v8 |
371 | 370 |
372 #endif // V8_COMPILER_INSTRUCTION_SELECTOR_IMPL_H_ | 371 #endif // V8_COMPILER_INSTRUCTION_SELECTOR_IMPL_H_ |
OLD | NEW |