Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(19)

Side by Side Diff: src/compiler/instruction.h

Issue 1070043002: [turbofan] Push layout descriptors to InstructionOperand subclasses. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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_H_ 5 #ifndef V8_COMPILER_INSTRUCTION_H_
6 #define V8_COMPILER_INSTRUCTION_H_ 6 #define V8_COMPILER_INSTRUCTION_H_
7 7
8 #include <deque> 8 #include <deque>
9 #include <iosfwd> 9 #include <iosfwd>
10 #include <map> 10 #include <map>
(...skipping 17 matching lines...) Expand all
28 const InstructionCode kSourcePositionInstruction = -1; 28 const InstructionCode kSourcePositionInstruction = -1;
29 29
30 class InstructionOperand { 30 class InstructionOperand {
31 public: 31 public:
32 static const int kInvalidVirtualRegister = -1; 32 static const int kInvalidVirtualRegister = -1;
33 33
34 // TODO(dcarney): recover bit. INVALID can be represented as UNALLOCATED with 34 // TODO(dcarney): recover bit. INVALID can be represented as UNALLOCATED with
35 // kInvalidVirtualRegister and some DCHECKS. 35 // kInvalidVirtualRegister and some DCHECKS.
36 enum Kind { INVALID, UNALLOCATED, CONSTANT, IMMEDIATE, ALLOCATED }; 36 enum Kind { INVALID, UNALLOCATED, CONSTANT, IMMEDIATE, ALLOCATED };
37 37
38 InstructionOperand() 38 InstructionOperand() : InstructionOperand(INVALID) {}
39 : InstructionOperand(INVALID, 0, kInvalidVirtualRegister) {}
40 39
41 Kind kind() const { return KindField::decode(value_); } 40 Kind kind() const { return KindField::decode(value_); }
42 41
43 #define INSTRUCTION_OPERAND_PREDICATE(name, type) \ 42 #define INSTRUCTION_OPERAND_PREDICATE(name, type) \
44 bool Is##name() const { return kind() == type; } 43 bool Is##name() const { return kind() == type; }
45 INSTRUCTION_OPERAND_PREDICATE(Invalid, INVALID) 44 INSTRUCTION_OPERAND_PREDICATE(Invalid, INVALID)
46 INSTRUCTION_OPERAND_PREDICATE(Unallocated, UNALLOCATED) 45 INSTRUCTION_OPERAND_PREDICATE(Unallocated, UNALLOCATED)
47 INSTRUCTION_OPERAND_PREDICATE(Constant, CONSTANT) 46 INSTRUCTION_OPERAND_PREDICATE(Constant, CONSTANT)
48 INSTRUCTION_OPERAND_PREDICATE(Immediate, IMMEDIATE) 47 INSTRUCTION_OPERAND_PREDICATE(Immediate, IMMEDIATE)
49 INSTRUCTION_OPERAND_PREDICATE(Allocated, ALLOCATED) 48 INSTRUCTION_OPERAND_PREDICATE(Allocated, ALLOCATED)
(...skipping 18 matching lines...) Expand all
68 void* buffer = zone->New(sizeof(op)); 67 void* buffer = zone->New(sizeof(op));
69 return new (buffer) SubKindOperand(op); 68 return new (buffer) SubKindOperand(op);
70 } 69 }
71 70
72 static void ReplaceWith(InstructionOperand* dest, 71 static void ReplaceWith(InstructionOperand* dest,
73 const InstructionOperand* src) { 72 const InstructionOperand* src) {
74 *dest = *src; 73 *dest = *src;
75 } 74 }
76 75
77 protected: 76 protected:
78 InstructionOperand(Kind kind, int index, int virtual_register) { 77 explicit InstructionOperand(Kind kind) : value_(KindField::encode(kind)) {}
79 if (kind != UNALLOCATED && kind != CONSTANT) {
80 DCHECK(virtual_register == kInvalidVirtualRegister);
81 }
82 value_ = KindField::encode(kind);
83 value_ |=
84 VirtualRegisterField::encode(static_cast<uint32_t>(virtual_register));
85 value_ |= static_cast<int64_t>(index) << IndexField::kShift;
86 }
87 78
88 typedef BitField64<Kind, 0, 3> KindField; 79 class KindField : public BitField64<Kind, 0, 3> {};
89 typedef BitField64<uint32_t, 3, 32> VirtualRegisterField;
90 typedef BitField64<int32_t, 35, 29> IndexField;
91 80
92 uint64_t value_; 81 uint64_t value_;
93 }; 82 };
94 83
95 struct PrintableInstructionOperand { 84 struct PrintableInstructionOperand {
96 const RegisterConfiguration* register_configuration_; 85 const RegisterConfiguration* register_configuration_;
97 const InstructionOperand* op_; 86 const InstructionOperand* op_;
98 }; 87 };
99 88
100 std::ostream& operator<<(std::ostream& os, 89 std::ostream& operator<<(std::ostream& os,
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
139 // output). 128 // output).
140 USED_AT_START, 129 USED_AT_START,
141 130
142 // USED_AT_END operand is treated as live until the end of 131 // USED_AT_END operand is treated as live until the end of
143 // instruction. This means that register allocator will not reuse it's 132 // instruction. This means that register allocator will not reuse it's
144 // register for any other operand inside instruction. 133 // register for any other operand inside instruction.
145 USED_AT_END 134 USED_AT_END
146 }; 135 };
147 136
148 UnallocatedOperand(ExtendedPolicy policy, int virtual_register) 137 UnallocatedOperand(ExtendedPolicy policy, int virtual_register)
149 : InstructionOperand(UNALLOCATED, 0, virtual_register) { 138 : UnallocatedOperand(virtual_register) {
150 value_ |= BasicPolicyField::encode(EXTENDED_POLICY); 139 value_ |= BasicPolicyField::encode(EXTENDED_POLICY);
151 value_ |= ExtendedPolicyField::encode(policy); 140 value_ |= ExtendedPolicyField::encode(policy);
152 value_ |= LifetimeField::encode(USED_AT_END); 141 value_ |= LifetimeField::encode(USED_AT_END);
153 } 142 }
154 143
155 UnallocatedOperand(BasicPolicy policy, int index, int virtual_register) 144 UnallocatedOperand(BasicPolicy policy, int index, int virtual_register)
156 : InstructionOperand(UNALLOCATED, 0, virtual_register) { 145 : UnallocatedOperand(virtual_register) {
157 DCHECK(policy == FIXED_SLOT); 146 DCHECK(policy == FIXED_SLOT);
158 value_ |= BasicPolicyField::encode(policy); 147 value_ |= BasicPolicyField::encode(policy);
159 value_ |= static_cast<int64_t>(index) << FixedSlotIndexField::kShift; 148 value_ |= static_cast<int64_t>(index) << FixedSlotIndexField::kShift;
160 DCHECK(this->fixed_slot_index() == index); 149 DCHECK(this->fixed_slot_index() == index);
161 } 150 }
162 151
163 UnallocatedOperand(ExtendedPolicy policy, int index, int virtual_register) 152 UnallocatedOperand(ExtendedPolicy policy, int index, int virtual_register)
164 : InstructionOperand(UNALLOCATED, 0, virtual_register) { 153 : UnallocatedOperand(virtual_register) {
165 DCHECK(policy == FIXED_REGISTER || policy == FIXED_DOUBLE_REGISTER); 154 DCHECK(policy == FIXED_REGISTER || policy == FIXED_DOUBLE_REGISTER);
166 value_ |= BasicPolicyField::encode(EXTENDED_POLICY); 155 value_ |= BasicPolicyField::encode(EXTENDED_POLICY);
167 value_ |= ExtendedPolicyField::encode(policy); 156 value_ |= ExtendedPolicyField::encode(policy);
168 value_ |= LifetimeField::encode(USED_AT_END); 157 value_ |= LifetimeField::encode(USED_AT_END);
169 value_ |= FixedRegisterField::encode(index); 158 value_ |= FixedRegisterField::encode(index);
170 } 159 }
171 160
172 UnallocatedOperand(ExtendedPolicy policy, Lifetime lifetime, 161 UnallocatedOperand(ExtendedPolicy policy, Lifetime lifetime,
173 int virtual_register) 162 int virtual_register)
174 : InstructionOperand(UNALLOCATED, 0, virtual_register) { 163 : UnallocatedOperand(virtual_register) {
175 value_ |= BasicPolicyField::encode(EXTENDED_POLICY); 164 value_ |= BasicPolicyField::encode(EXTENDED_POLICY);
176 value_ |= ExtendedPolicyField::encode(policy); 165 value_ |= ExtendedPolicyField::encode(policy);
177 value_ |= LifetimeField::encode(lifetime); 166 value_ |= LifetimeField::encode(lifetime);
178 } 167 }
179 168
180 UnallocatedOperand* Copy(Zone* zone) { return New(zone, *this); } 169 UnallocatedOperand* Copy(Zone* zone) { return New(zone, *this); }
181 170
182 UnallocatedOperand* CopyUnconstrained(Zone* zone) { 171 UnallocatedOperand* CopyUnconstrained(Zone* zone) {
183 return New(zone, UnallocatedOperand(ANY, virtual_register())); 172 return New(zone, UnallocatedOperand(ANY, virtual_register()));
184 } 173 }
185 174
186 // The encoding used for UnallocatedOperand operands depends on the policy
187 // that is
188 // stored within the operand. The FIXED_SLOT policy uses a compact encoding
189 // because it accommodates a larger pay-load.
190 //
191 // For FIXED_SLOT policy:
192 // +------------------------------------------------+
193 // | slot_index | 0 | virtual_register | 001 |
194 // +------------------------------------------------+
195 //
196 // For all other (extended) policies:
197 // +-----------------------------------------------------+
198 // | reg_index | L | PPP | 1 | virtual_register | 001 |
199 // +-----------------------------------------------------+
200 // L ... Lifetime
201 // P ... Policy
202 //
203 // The slot index is a signed value which requires us to decode it manually
204 // instead of using the BitField utility class.
205
206 // All bits fit into the index field.
207 STATIC_ASSERT(IndexField::kShift == 35);
208
209 // BitFields for all unallocated operands.
210 class BasicPolicyField : public BitField64<BasicPolicy, 35, 1> {};
211
212 // BitFields specific to BasicPolicy::FIXED_SLOT.
213 class FixedSlotIndexField : public BitField64<int, 36, 28> {};
214
215 // BitFields specific to BasicPolicy::EXTENDED_POLICY.
216 class ExtendedPolicyField : public BitField64<ExtendedPolicy, 36, 3> {};
217 class LifetimeField : public BitField64<Lifetime, 39, 1> {};
218 class FixedRegisterField : public BitField64<int, 40, 6> {};
219
220 // Predicates for the operand policy. 175 // Predicates for the operand policy.
221 bool HasAnyPolicy() const { 176 bool HasAnyPolicy() const {
222 return basic_policy() == EXTENDED_POLICY && extended_policy() == ANY; 177 return basic_policy() == EXTENDED_POLICY && extended_policy() == ANY;
223 } 178 }
224 bool HasFixedPolicy() const { 179 bool HasFixedPolicy() const {
225 return basic_policy() == FIXED_SLOT || 180 return basic_policy() == FIXED_SLOT ||
226 extended_policy() == FIXED_REGISTER || 181 extended_policy() == FIXED_REGISTER ||
227 extended_policy() == FIXED_DOUBLE_REGISTER; 182 extended_policy() == FIXED_DOUBLE_REGISTER;
228 } 183 }
229 bool HasRegisterPolicy() const { 184 bool HasRegisterPolicy() const {
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
285 value_ = VirtualRegisterField::update(value_, static_cast<uint32_t>(id)); 240 value_ = VirtualRegisterField::update(value_, static_cast<uint32_t>(id));
286 } 241 }
287 242
288 // [lifetime]: Only for non-FIXED_SLOT. 243 // [lifetime]: Only for non-FIXED_SLOT.
289 bool IsUsedAtStart() const { 244 bool IsUsedAtStart() const {
290 DCHECK(basic_policy() == EXTENDED_POLICY); 245 DCHECK(basic_policy() == EXTENDED_POLICY);
291 return LifetimeField::decode(value_) == USED_AT_START; 246 return LifetimeField::decode(value_) == USED_AT_START;
292 } 247 }
293 248
294 INSTRUCTION_OPERAND_CASTS(UnallocatedOperand, UNALLOCATED); 249 INSTRUCTION_OPERAND_CASTS(UnallocatedOperand, UNALLOCATED);
250
251 // The encoding used for UnallocatedOperand operands depends on the policy
252 // that is
253 // stored within the operand. The FIXED_SLOT policy uses a compact encoding
254 // because it accommodates a larger pay-load.
255 //
256 // For FIXED_SLOT policy:
257 // +------------------------------------------------+
258 // | slot_index | 0 | virtual_register | 001 |
259 // +------------------------------------------------+
260 //
261 // For all other (extended) policies:
262 // +-----------------------------------------------------+
263 // | reg_index | L | PPP | 1 | virtual_register | 001 |
264 // +-----------------------------------------------------+
265 // L ... Lifetime
266 // P ... Policy
267 //
268 // The slot index is a signed value which requires us to decode it manually
269 // instead of using the BitField utility class.
270
271 STATIC_ASSERT(KindField::kSize == 3);
272
273 class VirtualRegisterField : public BitField64<uint32_t, 3, 32> {};
274
275 // BitFields for all unallocated operands.
276 class BasicPolicyField : public BitField64<BasicPolicy, 35, 1> {};
277
278 // BitFields specific to BasicPolicy::FIXED_SLOT.
279 class FixedSlotIndexField : public BitField64<int, 36, 28> {};
280
281 // BitFields specific to BasicPolicy::EXTENDED_POLICY.
282 class ExtendedPolicyField : public BitField64<ExtendedPolicy, 36, 3> {};
283 class LifetimeField : public BitField64<Lifetime, 39, 1> {};
284 class FixedRegisterField : public BitField64<int, 40, 6> {};
285
286 private:
287 explicit UnallocatedOperand(int virtual_register)
288 : InstructionOperand(UNALLOCATED) {
289 value_ |=
290 VirtualRegisterField::encode(static_cast<uint32_t>(virtual_register));
291 }
295 }; 292 };
296 293
297 294
298 class ConstantOperand : public InstructionOperand { 295 class ConstantOperand : public InstructionOperand {
299 public: 296 public:
300 explicit ConstantOperand(int virtual_register) 297 explicit ConstantOperand(int virtual_register)
301 : InstructionOperand(CONSTANT, 0, virtual_register) {} 298 : InstructionOperand(CONSTANT) {
299 value_ |=
300 VirtualRegisterField::encode(static_cast<uint32_t>(virtual_register));
301 }
302 302
303 int32_t virtual_register() const { 303 int32_t virtual_register() const {
304 return static_cast<int32_t>(VirtualRegisterField::decode(value_)); 304 return static_cast<int32_t>(VirtualRegisterField::decode(value_));
305 } 305 }
306 306
307 static ConstantOperand* New(Zone* zone, int virtual_register) { 307 static ConstantOperand* New(Zone* zone, int virtual_register) {
308 return InstructionOperand::New(zone, ConstantOperand(virtual_register)); 308 return InstructionOperand::New(zone, ConstantOperand(virtual_register));
309 } 309 }
310 310
311 INSTRUCTION_OPERAND_CASTS(ConstantOperand, CONSTANT); 311 INSTRUCTION_OPERAND_CASTS(ConstantOperand, CONSTANT);
312
313 STATIC_ASSERT(KindField::kSize == 3);
314 class VirtualRegisterField : public BitField64<uint32_t, 3, 32> {};
312 }; 315 };
313 316
314 317
315 class ImmediateOperand : public InstructionOperand { 318 class ImmediateOperand : public InstructionOperand {
316 public: 319 public:
317 explicit ImmediateOperand(int index) 320 explicit ImmediateOperand(int index) : InstructionOperand(IMMEDIATE) {
318 : InstructionOperand(IMMEDIATE, index, kInvalidVirtualRegister) {} 321 value_ |= static_cast<int64_t>(index) << IndexField::kShift;
322 }
319 323
320 int index() const { 324 int index() const {
321 return static_cast<int64_t>(value_) >> IndexField::kShift; 325 return static_cast<int64_t>(value_) >> IndexField::kShift;
322 } 326 }
323 327
324 static ImmediateOperand* New(Zone* zone, int index) { 328 static ImmediateOperand* New(Zone* zone, int index) {
325 return InstructionOperand::New(zone, ImmediateOperand(index)); 329 return InstructionOperand::New(zone, ImmediateOperand(index));
326 } 330 }
327 331
328 INSTRUCTION_OPERAND_CASTS(ImmediateOperand, IMMEDIATE); 332 INSTRUCTION_OPERAND_CASTS(ImmediateOperand, IMMEDIATE);
333
334 STATIC_ASSERT(KindField::kSize == 3);
335 class IndexField : public BitField64<int32_t, 35, 29> {};
329 }; 336 };
330 337
331 338
332 class AllocatedOperand : public InstructionOperand { 339 class AllocatedOperand : public InstructionOperand {
333 public: 340 public:
334 enum AllocatedKind { 341 enum AllocatedKind {
335 STACK_SLOT, 342 STACK_SLOT,
336 DOUBLE_STACK_SLOT, 343 DOUBLE_STACK_SLOT,
337 REGISTER, 344 REGISTER,
338 DOUBLE_REGISTER 345 DOUBLE_REGISTER
339 }; 346 };
340 347
341 AllocatedOperand(AllocatedKind kind, int index) 348 AllocatedOperand(AllocatedKind kind, int index)
342 : InstructionOperand(ALLOCATED, index, kInvalidVirtualRegister) { 349 : InstructionOperand(ALLOCATED) {
343 if (kind == REGISTER || kind == DOUBLE_REGISTER) DCHECK(index >= 0); 350 DCHECK_IMPLIES(kind == REGISTER || kind == DOUBLE_REGISTER, index >= 0);
344 value_ = AllocatedKindField::update(value_, kind); 351 value_ |= AllocatedKindField::encode(kind);
352 value_ |= static_cast<int64_t>(index) << IndexField::kShift;
345 } 353 }
346 354
347 int index() const { 355 int index() const {
348 return static_cast<int64_t>(value_) >> IndexField::kShift; 356 return static_cast<int64_t>(value_) >> IndexField::kShift;
349 } 357 }
350 358
351 AllocatedKind allocated_kind() const { 359 AllocatedKind allocated_kind() const {
352 return AllocatedKindField::decode(value_); 360 return AllocatedKindField::decode(value_);
353 } 361 }
354 362
355 static AllocatedOperand* New(Zone* zone, AllocatedKind kind, int index) { 363 static AllocatedOperand* New(Zone* zone, AllocatedKind kind, int index) {
356 return InstructionOperand::New(zone, AllocatedOperand(kind, index)); 364 return InstructionOperand::New(zone, AllocatedOperand(kind, index));
357 } 365 }
358 366
359 INSTRUCTION_OPERAND_CASTS(AllocatedOperand, ALLOCATED); 367 INSTRUCTION_OPERAND_CASTS(AllocatedOperand, ALLOCATED);
360 368
361 private: 369 STATIC_ASSERT(KindField::kSize == 3);
362 typedef BitField64<AllocatedKind, 3, 2> AllocatedKindField; 370 class AllocatedKindField : public BitField64<AllocatedKind, 3, 2> {};
371 class IndexField : public BitField64<int32_t, 35, 29> {};
363 }; 372 };
364 373
365 374
366 #undef INSTRUCTION_OPERAND_CASTS 375 #undef INSTRUCTION_OPERAND_CASTS
367 376
368 377
369 #define ALLOCATED_OPERAND_LIST(V) \ 378 #define ALLOCATED_OPERAND_LIST(V) \
370 V(StackSlot, STACK_SLOT) \ 379 V(StackSlot, STACK_SLOT) \
371 V(DoubleStackSlot, DOUBLE_STACK_SLOT) \ 380 V(DoubleStackSlot, DOUBLE_STACK_SLOT) \
372 V(Register, REGISTER) \ 381 V(Register, REGISTER) \
(...skipping 741 matching lines...) Expand 10 before | Expand all | Expand 10 after
1114 1123
1115 1124
1116 std::ostream& operator<<(std::ostream& os, 1125 std::ostream& operator<<(std::ostream& os,
1117 const PrintableInstructionSequence& code); 1126 const PrintableInstructionSequence& code);
1118 1127
1119 } // namespace compiler 1128 } // namespace compiler
1120 } // namespace internal 1129 } // namespace internal
1121 } // namespace v8 1130 } // namespace v8
1122 1131
1123 #endif // V8_COMPILER_INSTRUCTION_H_ 1132 #endif // V8_COMPILER_INSTRUCTION_H_
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698