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

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

Issue 1075863002: [turbofan] Make AllocatedOperand an InstructionOperand::Kind. (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 | src/compiler/instruction.cc » ('j') | 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>
11 #include <set> 11 #include <set>
12 12
13 #include "src/compiler/common-operator.h" 13 #include "src/compiler/common-operator.h"
14 #include "src/compiler/frame.h" 14 #include "src/compiler/frame.h"
15 #include "src/compiler/instruction-codes.h" 15 #include "src/compiler/instruction-codes.h"
16 #include "src/compiler/opcodes.h" 16 #include "src/compiler/opcodes.h"
17 #include "src/compiler/register-configuration.h" 17 #include "src/compiler/register-configuration.h"
18 #include "src/compiler/source-position.h" 18 #include "src/compiler/source-position.h"
19 #include "src/zone-allocator.h" 19 #include "src/zone-allocator.h"
20 20
21 namespace v8 { 21 namespace v8 {
22 namespace internal { 22 namespace internal {
23 namespace compiler { 23 namespace compiler {
24 24
25 class Schedule; 25 class Schedule;
26 26
27 // A couple of reserved opcodes are used for internal use. 27 // A couple of reserved opcodes are used for internal use.
28 const InstructionCode kSourcePositionInstruction = -1; 28 const InstructionCode kSourcePositionInstruction = -1;
29 29
30 #define ALLOCATED_OPERAND_LIST(V) \
31 V(StackSlot, STACK_SLOT) \
32 V(DoubleStackSlot, DOUBLE_STACK_SLOT) \
33 V(Register, REGISTER) \
34 V(DoubleRegister, DOUBLE_REGISTER)
35
36 class InstructionOperand { 30 class InstructionOperand {
37 public: 31 public:
38 static const int kInvalidVirtualRegister = -1; 32 static const int kInvalidVirtualRegister = -1;
39 33
40 enum Kind { 34 // TODO(dcarney): recover bit. INVALID can be represented as UNALLOCATED with
41 INVALID, 35 // kInvalidVirtualRegister and some DCHECKS.
42 UNALLOCATED, 36 enum Kind { INVALID, UNALLOCATED, CONSTANT, IMMEDIATE, ALLOCATED };
43 CONSTANT,
44 IMMEDIATE,
45 STACK_SLOT,
46 DOUBLE_STACK_SLOT,
47 REGISTER,
48 DOUBLE_REGISTER
49 };
50 37
51 InstructionOperand() 38 InstructionOperand()
52 : InstructionOperand(INVALID, 0, kInvalidVirtualRegister) {} 39 : InstructionOperand(INVALID, 0, kInvalidVirtualRegister) {}
53 40
54 Kind kind() const { return KindField::decode(value_); } 41 Kind kind() const { return KindField::decode(value_); }
55 42
56 #define INSTRUCTION_OPERAND_PREDICATE(name, type) \ 43 #define INSTRUCTION_OPERAND_PREDICATE(name, type) \
57 bool Is##name() const { return kind() == type; } 44 bool Is##name() const { return kind() == type; }
58 ALLOCATED_OPERAND_LIST(INSTRUCTION_OPERAND_PREDICATE) 45 INSTRUCTION_OPERAND_PREDICATE(Invalid, INVALID)
46 INSTRUCTION_OPERAND_PREDICATE(Unallocated, UNALLOCATED)
59 INSTRUCTION_OPERAND_PREDICATE(Constant, CONSTANT) 47 INSTRUCTION_OPERAND_PREDICATE(Constant, CONSTANT)
60 INSTRUCTION_OPERAND_PREDICATE(Immediate, IMMEDIATE) 48 INSTRUCTION_OPERAND_PREDICATE(Immediate, IMMEDIATE)
61 INSTRUCTION_OPERAND_PREDICATE(Unallocated, UNALLOCATED) 49 INSTRUCTION_OPERAND_PREDICATE(Allocated, ALLOCATED)
62 INSTRUCTION_OPERAND_PREDICATE(Invalid, INVALID)
63 #undef INSTRUCTION_OPERAND_PREDICATE 50 #undef INSTRUCTION_OPERAND_PREDICATE
64 51
52 inline bool IsRegister() const;
53 inline bool IsDoubleRegister() const;
54 inline bool IsStackSlot() const;
55 inline bool IsDoubleStackSlot() const;
56
65 bool Equals(const InstructionOperand* other) const { 57 bool Equals(const InstructionOperand* other) const {
66 return value_ == other->value_; 58 return value_ == other->value_;
67 } 59 }
68 60
69 // Useful for map/set keys. 61 // Useful for map/set keys.
70 bool operator<(const InstructionOperand& op) const { 62 bool operator<(const InstructionOperand& op) const {
71 return value_ < op.value_; 63 return value_ < op.value_;
72 } 64 }
73 65
74 template <typename SubKindOperand> 66 template <typename SubKindOperand>
75 static SubKindOperand* New(Zone* zone, const SubKindOperand& op) { 67 static SubKindOperand* New(Zone* zone, const SubKindOperand& op) {
76 void* buffer = zone->New(sizeof(op)); 68 void* buffer = zone->New(sizeof(op));
77 return new (buffer) SubKindOperand(op); 69 return new (buffer) SubKindOperand(op);
78 } 70 }
79 71
80 static void ReplaceWith(InstructionOperand* dest, 72 static void ReplaceWith(InstructionOperand* dest,
81 const InstructionOperand* src) { 73 const InstructionOperand* src) {
82 *dest = *src; 74 *dest = *src;
83 } 75 }
84 76
85 protected: 77 protected:
86 InstructionOperand(Kind kind, int index, int virtual_register) { 78 InstructionOperand(Kind kind, int index, int virtual_register) {
87 if (kind == REGISTER || kind == DOUBLE_REGISTER) DCHECK(index >= 0);
88 if (kind != UNALLOCATED && kind != CONSTANT) { 79 if (kind != UNALLOCATED && kind != CONSTANT) {
89 DCHECK(virtual_register == kInvalidVirtualRegister); 80 DCHECK(virtual_register == kInvalidVirtualRegister);
90 } 81 }
91 value_ = KindField::encode(kind); 82 value_ = KindField::encode(kind);
92 value_ |= 83 value_ |=
93 VirtualRegisterField::encode(static_cast<uint32_t>(virtual_register)); 84 VirtualRegisterField::encode(static_cast<uint32_t>(virtual_register));
94 value_ |= static_cast<int64_t>(index) << IndexField::kShift; 85 value_ |= static_cast<int64_t>(index) << IndexField::kShift;
95 } 86 }
96 87
97 typedef BitField64<Kind, 0, 3> KindField; 88 typedef BitField64<Kind, 0, 3> KindField;
98 typedef BitField64<uint32_t, 3, 32> VirtualRegisterField; 89 typedef BitField64<uint32_t, 3, 32> VirtualRegisterField;
99 typedef BitField64<int32_t, 35, 29> IndexField; 90 typedef BitField64<int32_t, 35, 29> IndexField;
100 91
101 uint64_t value_; 92 uint64_t value_;
102 }; 93 };
103 94
104 struct PrintableInstructionOperand { 95 struct PrintableInstructionOperand {
105 const RegisterConfiguration* register_configuration_; 96 const RegisterConfiguration* register_configuration_;
106 const InstructionOperand* op_; 97 const InstructionOperand* op_;
107 }; 98 };
108 99
109 std::ostream& operator<<(std::ostream& os, 100 std::ostream& operator<<(std::ostream& os,
110 const PrintableInstructionOperand& op); 101 const PrintableInstructionOperand& op);
111 102
103 #define INSTRUCTION_OPERAND_CASTS(OperandType, OperandKind) \
104 \
105 static OperandType* cast(InstructionOperand* op) { \
106 DCHECK_EQ(OperandKind, op->kind()); \
107 return static_cast<OperandType*>(op); \
108 } \
109 \
110 static const OperandType* cast(const InstructionOperand* op) { \
111 DCHECK_EQ(OperandKind, op->kind()); \
112 return static_cast<const OperandType*>(op); \
113 } \
114 \
115 static OperandType cast(const InstructionOperand& op) { \
116 DCHECK_EQ(OperandKind, op.kind()); \
117 return *static_cast<const OperandType*>(&op); \
118 }
119
112 class UnallocatedOperand : public InstructionOperand { 120 class UnallocatedOperand : public InstructionOperand {
113 public: 121 public:
114 enum BasicPolicy { FIXED_SLOT, EXTENDED_POLICY }; 122 enum BasicPolicy { FIXED_SLOT, EXTENDED_POLICY };
115 123
116 enum ExtendedPolicy { 124 enum ExtendedPolicy {
117 NONE, 125 NONE,
118 ANY, 126 ANY,
119 FIXED_REGISTER, 127 FIXED_REGISTER,
120 FIXED_DOUBLE_REGISTER, 128 FIXED_DOUBLE_REGISTER,
121 MUST_HAVE_REGISTER, 129 MUST_HAVE_REGISTER,
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
168 value_ |= ExtendedPolicyField::encode(policy); 176 value_ |= ExtendedPolicyField::encode(policy);
169 value_ |= LifetimeField::encode(lifetime); 177 value_ |= LifetimeField::encode(lifetime);
170 } 178 }
171 179
172 UnallocatedOperand* Copy(Zone* zone) { return New(zone, *this); } 180 UnallocatedOperand* Copy(Zone* zone) { return New(zone, *this); }
173 181
174 UnallocatedOperand* CopyUnconstrained(Zone* zone) { 182 UnallocatedOperand* CopyUnconstrained(Zone* zone) {
175 return New(zone, UnallocatedOperand(ANY, virtual_register())); 183 return New(zone, UnallocatedOperand(ANY, virtual_register()));
176 } 184 }
177 185
178 static const UnallocatedOperand* cast(const InstructionOperand* op) {
179 DCHECK(op->IsUnallocated());
180 return static_cast<const UnallocatedOperand*>(op);
181 }
182
183 static UnallocatedOperand* cast(InstructionOperand* op) {
184 DCHECK(op->IsUnallocated());
185 return static_cast<UnallocatedOperand*>(op);
186 }
187
188 static UnallocatedOperand cast(const InstructionOperand& op) {
189 DCHECK(op.IsUnallocated());
190 return *static_cast<const UnallocatedOperand*>(&op);
191 }
192
193 // The encoding used for UnallocatedOperand operands depends on the policy 186 // The encoding used for UnallocatedOperand operands depends on the policy
194 // that is 187 // that is
195 // stored within the operand. The FIXED_SLOT policy uses a compact encoding 188 // stored within the operand. The FIXED_SLOT policy uses a compact encoding
196 // because it accommodates a larger pay-load. 189 // because it accommodates a larger pay-load.
197 // 190 //
198 // For FIXED_SLOT policy: 191 // For FIXED_SLOT policy:
199 // +------------------------------------------------+ 192 // +------------------------------------------------+
200 // | slot_index | 0 | virtual_register | 001 | 193 // | slot_index | 0 | virtual_register | 001 |
201 // +------------------------------------------------+ 194 // +------------------------------------------------+
202 // 195 //
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
290 void set_virtual_register(int32_t id) { 283 void set_virtual_register(int32_t id) {
291 DCHECK_EQ(UNALLOCATED, kind()); 284 DCHECK_EQ(UNALLOCATED, kind());
292 value_ = VirtualRegisterField::update(value_, static_cast<uint32_t>(id)); 285 value_ = VirtualRegisterField::update(value_, static_cast<uint32_t>(id));
293 } 286 }
294 287
295 // [lifetime]: Only for non-FIXED_SLOT. 288 // [lifetime]: Only for non-FIXED_SLOT.
296 bool IsUsedAtStart() const { 289 bool IsUsedAtStart() const {
297 DCHECK(basic_policy() == EXTENDED_POLICY); 290 DCHECK(basic_policy() == EXTENDED_POLICY);
298 return LifetimeField::decode(value_) == USED_AT_START; 291 return LifetimeField::decode(value_) == USED_AT_START;
299 } 292 }
293
294 INSTRUCTION_OPERAND_CASTS(UnallocatedOperand, UNALLOCATED);
300 }; 295 };
301 296
302 297
303 class ConstantOperand : public InstructionOperand { 298 class ConstantOperand : public InstructionOperand {
304 public: 299 public:
305 explicit ConstantOperand(int virtual_register) 300 explicit ConstantOperand(int virtual_register)
306 : InstructionOperand(CONSTANT, 0, virtual_register) {} 301 : InstructionOperand(CONSTANT, 0, virtual_register) {}
307 302
308 int32_t virtual_register() const { 303 int32_t virtual_register() const {
309 return static_cast<int32_t>(VirtualRegisterField::decode(value_)); 304 return static_cast<int32_t>(VirtualRegisterField::decode(value_));
310 } 305 }
311 306
312 static ConstantOperand* New(Zone* zone, int virtual_register) { 307 static ConstantOperand* New(Zone* zone, int virtual_register) {
313 return InstructionOperand::New(zone, ConstantOperand(virtual_register)); 308 return InstructionOperand::New(zone, ConstantOperand(virtual_register));
314 } 309 }
315 310
316 static ConstantOperand* cast(InstructionOperand* op) { 311 INSTRUCTION_OPERAND_CASTS(ConstantOperand, CONSTANT);
317 DCHECK(op->kind() == CONSTANT);
318 return static_cast<ConstantOperand*>(op);
319 }
320
321 static const ConstantOperand* cast(const InstructionOperand* op) {
322 DCHECK(op->kind() == CONSTANT);
323 return static_cast<const ConstantOperand*>(op);
324 }
325
326 static ConstantOperand cast(const InstructionOperand& op) {
327 DCHECK(op.kind() == CONSTANT);
328 return *static_cast<const ConstantOperand*>(&op);
329 }
330 }; 312 };
331 313
332 314
333 class ImmediateOperand : public InstructionOperand { 315 class ImmediateOperand : public InstructionOperand {
334 public: 316 public:
335 explicit ImmediateOperand(int index) 317 explicit ImmediateOperand(int index)
336 : InstructionOperand(IMMEDIATE, index, kInvalidVirtualRegister) {} 318 : InstructionOperand(IMMEDIATE, index, kInvalidVirtualRegister) {}
337 319
338 int index() const { 320 int index() const {
339 return static_cast<int64_t>(value_) >> IndexField::kShift; 321 return static_cast<int64_t>(value_) >> IndexField::kShift;
340 } 322 }
341 323
342 static ImmediateOperand* New(Zone* zone, int index) { 324 static ImmediateOperand* New(Zone* zone, int index) {
343 return InstructionOperand::New(zone, ImmediateOperand(index)); 325 return InstructionOperand::New(zone, ImmediateOperand(index));
344 } 326 }
345 327
346 static ImmediateOperand* cast(InstructionOperand* op) { 328 INSTRUCTION_OPERAND_CASTS(ImmediateOperand, IMMEDIATE);
347 DCHECK(op->kind() == IMMEDIATE);
348 return static_cast<ImmediateOperand*>(op);
349 }
350
351 static const ImmediateOperand* cast(const InstructionOperand* op) {
352 DCHECK(op->kind() == IMMEDIATE);
353 return static_cast<const ImmediateOperand*>(op);
354 }
355
356 static ImmediateOperand cast(const InstructionOperand& op) {
357 DCHECK(op.kind() == IMMEDIATE);
358 return *static_cast<const ImmediateOperand*>(&op);
359 }
360 }; 329 };
361 330
362 331
363 class AllocatedOperand : public InstructionOperand { 332 class AllocatedOperand : public InstructionOperand {
364 #define ALLOCATED_OPERAND_CHECK(Name, Kind) || kind == Kind 333 public:
365 #define CHECK_ALLOCATED_KIND() \ 334 enum AllocatedKind {
366 DCHECK(false ALLOCATED_OPERAND_LIST(ALLOCATED_OPERAND_CHECK)); \ 335 STACK_SLOT,
367 USE(kind); 336 DOUBLE_STACK_SLOT,
337 REGISTER,
338 DOUBLE_REGISTER
339 };
368 340
369 public: 341 AllocatedOperand(AllocatedKind kind, int index)
342 : InstructionOperand(ALLOCATED, index, kInvalidVirtualRegister) {
343 if (kind == REGISTER || kind == DOUBLE_REGISTER) DCHECK(index >= 0);
344 value_ = AllocatedKindField::update(value_, kind);
345 }
346
370 int index() const { 347 int index() const {
371 return static_cast<int64_t>(value_) >> IndexField::kShift; 348 return static_cast<int64_t>(value_) >> IndexField::kShift;
372 } 349 }
373 350
374 AllocatedOperand(Kind kind, int index) 351 AllocatedKind allocated_kind() const {
375 : InstructionOperand(kind, index, kInvalidVirtualRegister) { 352 return AllocatedKindField::decode(value_);
376 CHECK_ALLOCATED_KIND();
377 } 353 }
378 354
379 static AllocatedOperand* New(Zone* zone, Kind kind, int index) { 355 static AllocatedOperand* New(Zone* zone, AllocatedKind kind, int index) {
380 return InstructionOperand::New(zone, AllocatedOperand(kind, index)); 356 return InstructionOperand::New(zone, AllocatedOperand(kind, index));
381 } 357 }
382 358
383 static AllocatedOperand* cast(InstructionOperand* op) { 359 INSTRUCTION_OPERAND_CASTS(AllocatedOperand, ALLOCATED);
384 Kind kind = op->kind();
385 CHECK_ALLOCATED_KIND();
386 return static_cast<AllocatedOperand*>(op);
387 }
388 360
389 static const AllocatedOperand* cast(const InstructionOperand* op) { 361 private:
390 Kind kind = op->kind(); 362 typedef BitField64<AllocatedKind, 3, 2> AllocatedKindField;
391 CHECK_ALLOCATED_KIND();
392 return static_cast<const AllocatedOperand*>(op);
393 }
394
395 static AllocatedOperand cast(const InstructionOperand& op) {
396 Kind kind = op.kind();
397 CHECK_ALLOCATED_KIND();
398 return *static_cast<const AllocatedOperand*>(&op);
399 }
400
401 #undef CHECK_ALLOCATED_KIND
402 #undef ALLOCATED_OPERAND_CAST_CHECK
403 }; 363 };
404 364
405 365
406 #define INSTRUCTION_SUBKIND_OPERAND_CLASS(SubKind, kOperandKind) \ 366 #undef INSTRUCTION_OPERAND_CASTS
407 class SubKind##Operand FINAL : public AllocatedOperand { \ 367
408 public: \ 368
409 explicit SubKind##Operand(int index) \ 369 #define ALLOCATED_OPERAND_LIST(V) \
410 : AllocatedOperand(kOperandKind, index) {} \ 370 V(StackSlot, STACK_SLOT) \
411 \ 371 V(DoubleStackSlot, DOUBLE_STACK_SLOT) \
412 static SubKind##Operand* New(Zone* zone, int index) { \ 372 V(Register, REGISTER) \
413 return InstructionOperand::New(zone, SubKind##Operand(index)); \ 373 V(DoubleRegister, DOUBLE_REGISTER)
414 } \ 374
415 \ 375
416 static SubKind##Operand* cast(InstructionOperand* op) { \ 376 #define ALLOCATED_OPERAND_IS(SubKind, kOperandKind) \
417 DCHECK(op->kind() == kOperandKind); \ 377 bool InstructionOperand::Is##SubKind() const { \
418 return reinterpret_cast<SubKind##Operand*>(op); \ 378 return IsAllocated() && \
419 } \ 379 AllocatedOperand::cast(this)->allocated_kind() == \
420 \ 380 AllocatedOperand::kOperandKind; \
421 static const SubKind##Operand* cast(const InstructionOperand* op) { \ 381 }
422 DCHECK(op->kind() == kOperandKind); \ 382 ALLOCATED_OPERAND_LIST(ALLOCATED_OPERAND_IS)
423 return reinterpret_cast<const SubKind##Operand*>(op); \ 383 #undef ALLOCATED_OPERAND_IS
424 } \ 384
425 \ 385
426 static SubKind##Operand cast(const InstructionOperand& op) { \ 386 #define ALLOCATED_OPERAND_CLASS(SubKind, kOperandKind) \
427 DCHECK(op.kind() == kOperandKind); \ 387 class SubKind##Operand FINAL : public AllocatedOperand { \
428 return *static_cast<const SubKind##Operand*>(&op); \ 388 public: \
429 } \ 389 explicit SubKind##Operand(int index) \
390 : AllocatedOperand(kOperandKind, index) {} \
391 \
392 static SubKind##Operand* New(Zone* zone, int index) { \
393 return InstructionOperand::New(zone, SubKind##Operand(index)); \
394 } \
395 \
396 static SubKind##Operand* cast(InstructionOperand* op) { \
397 DCHECK_EQ(kOperandKind, AllocatedOperand::cast(op)->allocated_kind()); \
398 return reinterpret_cast<SubKind##Operand*>(op); \
399 } \
400 \
401 static const SubKind##Operand* cast(const InstructionOperand* op) { \
402 DCHECK_EQ(kOperandKind, AllocatedOperand::cast(op)->allocated_kind()); \
403 return reinterpret_cast<const SubKind##Operand*>(op); \
404 } \
405 \
406 static SubKind##Operand cast(const InstructionOperand& op) { \
407 DCHECK_EQ(kOperandKind, AllocatedOperand::cast(op).allocated_kind()); \
408 return *static_cast<const SubKind##Operand*>(&op); \
409 } \
430 }; 410 };
431 ALLOCATED_OPERAND_LIST(INSTRUCTION_SUBKIND_OPERAND_CLASS) 411 ALLOCATED_OPERAND_LIST(ALLOCATED_OPERAND_CLASS)
432 #undef INSTRUCTION_SUBKIND_OPERAND_CLASS 412 #undef ALLOCATED_OPERAND_CLASS
433 413
434 414
435 class MoveOperands FINAL { 415 class MoveOperands FINAL {
436 public: 416 public:
437 MoveOperands(InstructionOperand* source, InstructionOperand* destination) 417 MoveOperands(InstructionOperand* source, InstructionOperand* destination)
438 : source_(source), destination_(destination) {} 418 : source_(source), destination_(destination) {}
439 419
440 InstructionOperand* source() const { return source_; } 420 InstructionOperand* source() const { return source_; }
441 void set_source(InstructionOperand* operand) { source_ = operand; } 421 void set_source(InstructionOperand* operand) { source_ = operand; }
442 422
(...skipping 691 matching lines...) Expand 10 before | Expand all | Expand 10 after
1134 1114
1135 1115
1136 std::ostream& operator<<(std::ostream& os, 1116 std::ostream& operator<<(std::ostream& os,
1137 const PrintableInstructionSequence& code); 1117 const PrintableInstructionSequence& code);
1138 1118
1139 } // namespace compiler 1119 } // namespace compiler
1140 } // namespace internal 1120 } // namespace internal
1141 } // namespace v8 1121 } // namespace v8
1142 1122
1143 #endif // V8_COMPILER_INSTRUCTION_H_ 1123 #endif // V8_COMPILER_INSTRUCTION_H_
OLDNEW
« no previous file with comments | « no previous file | src/compiler/instruction.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698