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_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 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
53 InstructionOperand() : virtual_register_(kInvalidVirtualRegister) { | 53 InstructionOperand() : virtual_register_(kInvalidVirtualRegister) { |
54 ConvertTo(INVALID, 0); | 54 ConvertTo(INVALID, 0); |
55 } | 55 } |
56 | 56 |
57 InstructionOperand(Kind kind, int index) | 57 InstructionOperand(Kind kind, int index) |
58 : virtual_register_(kInvalidVirtualRegister) { | 58 : virtual_register_(kInvalidVirtualRegister) { |
59 DCHECK(kind != INVALID); | 59 DCHECK(kind != INVALID); |
60 ConvertTo(kind, index); | 60 ConvertTo(kind, index); |
61 } | 61 } |
62 | 62 |
| 63 static InstructionOperand* New(Zone* zone, Kind kind, int index) { |
| 64 return New(zone, InstructionOperand(kind, index)); |
| 65 } |
| 66 |
63 Kind kind() const { return KindField::decode(value_); } | 67 Kind kind() const { return KindField::decode(value_); } |
64 int index() const { return static_cast<int>(value_) >> KindField::kSize; } | 68 int index() const { return static_cast<int>(value_) >> KindField::kSize; } |
65 #define INSTRUCTION_OPERAND_PREDICATE(name, type) \ | 69 #define INSTRUCTION_OPERAND_PREDICATE(name, type) \ |
66 bool Is##name() const { return kind() == type; } | 70 bool Is##name() const { return kind() == type; } |
67 INSTRUCTION_OPERAND_LIST(INSTRUCTION_OPERAND_PREDICATE) | 71 INSTRUCTION_OPERAND_LIST(INSTRUCTION_OPERAND_PREDICATE) |
68 INSTRUCTION_OPERAND_PREDICATE(Unallocated, UNALLOCATED) | 72 INSTRUCTION_OPERAND_PREDICATE(Unallocated, UNALLOCATED) |
69 INSTRUCTION_OPERAND_PREDICATE(Invalid, INVALID) | 73 INSTRUCTION_OPERAND_PREDICATE(Invalid, INVALID) |
70 #undef INSTRUCTION_OPERAND_PREDICATE | 74 #undef INSTRUCTION_OPERAND_PREDICATE |
71 bool Equals(const InstructionOperand* other) const { | 75 bool Equals(const InstructionOperand* other) const { |
72 return value_ == other->value_; | 76 return value_ == other->value_; |
73 } | 77 } |
74 | 78 |
75 void ConvertTo(Kind kind, int index) { | 79 void ConvertTo(Kind kind, int index) { |
76 if (kind == REGISTER || kind == DOUBLE_REGISTER) DCHECK(index >= 0); | 80 if (kind == REGISTER || kind == DOUBLE_REGISTER) DCHECK(index >= 0); |
77 value_ = KindField::encode(kind); | 81 value_ = KindField::encode(kind); |
78 value_ |= bit_cast<unsigned>(index << KindField::kSize); | 82 value_ |= bit_cast<unsigned>(index << KindField::kSize); |
79 DCHECK(this->index() == index); | 83 DCHECK(this->index() == index); |
80 if (kind != UNALLOCATED) virtual_register_ = kInvalidVirtualRegister; | 84 if (kind != UNALLOCATED) virtual_register_ = kInvalidVirtualRegister; |
81 } | 85 } |
82 | 86 |
83 // TODO(dcarney): get rid of these | 87 protected: |
84 void* operator new(size_t, void* location) { return location; } | 88 template <typename SubKindOperand> |
85 void* operator new(size_t size, Zone* zone) { | 89 static SubKindOperand* New(Zone* zone, const SubKindOperand& op) { |
86 return zone->New(static_cast<int>(size)); | 90 void* buffer = zone->New(sizeof(op)); |
| 91 return new (buffer) SubKindOperand(op); |
87 } | 92 } |
88 void operator delete(void* pointer, Zone* zone) { UNREACHABLE(); } | |
89 | 93 |
90 protected: | |
91 InstructionOperand(Kind kind, int index, int virtual_register) | 94 InstructionOperand(Kind kind, int index, int virtual_register) |
92 : virtual_register_(virtual_register) { | 95 : virtual_register_(virtual_register) { |
93 ConvertTo(kind, index); | 96 ConvertTo(kind, index); |
94 } | 97 } |
95 typedef BitField<Kind, 0, 3> KindField; | 98 typedef BitField<Kind, 0, 3> KindField; |
96 | 99 |
97 uint32_t value_; | 100 uint32_t value_; |
98 // TODO(dcarney): this should really be unsigned. | 101 // TODO(dcarney): this should really be unsigned. |
99 int32_t virtual_register_; | 102 int32_t virtual_register_; |
100 }; | 103 }; |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
159 } | 162 } |
160 | 163 |
161 UnallocatedOperand(ExtendedPolicy policy, Lifetime lifetime, | 164 UnallocatedOperand(ExtendedPolicy policy, Lifetime lifetime, |
162 int virtual_register) | 165 int virtual_register) |
163 : InstructionOperand(UNALLOCATED, 0, virtual_register) { | 166 : InstructionOperand(UNALLOCATED, 0, virtual_register) { |
164 value_ |= BasicPolicyField::encode(EXTENDED_POLICY); | 167 value_ |= BasicPolicyField::encode(EXTENDED_POLICY); |
165 value_ |= ExtendedPolicyField::encode(policy); | 168 value_ |= ExtendedPolicyField::encode(policy); |
166 value_ |= LifetimeField::encode(lifetime); | 169 value_ |= LifetimeField::encode(lifetime); |
167 } | 170 } |
168 | 171 |
| 172 UnallocatedOperand* Copy(Zone* zone) { return New(zone, *this); } |
| 173 |
169 UnallocatedOperand* CopyUnconstrained(Zone* zone) { | 174 UnallocatedOperand* CopyUnconstrained(Zone* zone) { |
170 return new (zone) UnallocatedOperand(ANY, virtual_register()); | 175 return New(zone, UnallocatedOperand(ANY, virtual_register())); |
171 } | 176 } |
172 | 177 |
173 static const UnallocatedOperand* cast(const InstructionOperand* op) { | 178 static const UnallocatedOperand* cast(const InstructionOperand* op) { |
174 DCHECK(op->IsUnallocated()); | 179 DCHECK(op->IsUnallocated()); |
175 return static_cast<const UnallocatedOperand*>(op); | 180 return static_cast<const UnallocatedOperand*>(op); |
176 } | 181 } |
177 | 182 |
178 static UnallocatedOperand* cast(InstructionOperand* op) { | 183 static UnallocatedOperand* cast(InstructionOperand* op) { |
179 DCHECK(op->IsUnallocated()); | 184 DCHECK(op->IsUnallocated()); |
180 return static_cast<UnallocatedOperand*>(op); | 185 return static_cast<UnallocatedOperand*>(op); |
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
342 std::ostream& operator<<(std::ostream& os, const PrintableMoveOperands& mo); | 347 std::ostream& operator<<(std::ostream& os, const PrintableMoveOperands& mo); |
343 | 348 |
344 | 349 |
345 #define INSTRUCTION_SUBKIND_OPERAND_CLASS(SubKind, kOperandKind) \ | 350 #define INSTRUCTION_SUBKIND_OPERAND_CLASS(SubKind, kOperandKind) \ |
346 class SubKind##Operand FINAL : public InstructionOperand { \ | 351 class SubKind##Operand FINAL : public InstructionOperand { \ |
347 public: \ | 352 public: \ |
348 explicit SubKind##Operand(int index) \ | 353 explicit SubKind##Operand(int index) \ |
349 : InstructionOperand(kOperandKind, index) {} \ | 354 : InstructionOperand(kOperandKind, index) {} \ |
350 \ | 355 \ |
351 static SubKind##Operand* New(int index, Zone* zone) { \ | 356 static SubKind##Operand* New(int index, Zone* zone) { \ |
352 return new (zone) SubKind##Operand(index); \ | 357 return InstructionOperand::New(zone, SubKind##Operand(index)); \ |
353 } \ | 358 } \ |
354 \ | 359 \ |
355 static SubKind##Operand* cast(InstructionOperand* op) { \ | 360 static SubKind##Operand* cast(InstructionOperand* op) { \ |
356 DCHECK(op->kind() == kOperandKind); \ | 361 DCHECK(op->kind() == kOperandKind); \ |
357 return reinterpret_cast<SubKind##Operand*>(op); \ | 362 return reinterpret_cast<SubKind##Operand*>(op); \ |
358 } \ | 363 } \ |
359 \ | 364 \ |
360 static const SubKind##Operand* cast(const InstructionOperand* op) { \ | 365 static const SubKind##Operand* cast(const InstructionOperand* op) { \ |
361 DCHECK(op->kind() == kOperandKind); \ | 366 DCHECK(op->kind() == kOperandKind); \ |
362 return reinterpret_cast<const SubKind##Operand*>(op); \ | 367 return reinterpret_cast<const SubKind##Operand*>(op); \ |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
429 friend std::ostream& operator<<(std::ostream& os, const PointerMap& pm); | 434 friend std::ostream& operator<<(std::ostream& os, const PointerMap& pm); |
430 | 435 |
431 ZoneList<InstructionOperand*> pointer_operands_; | 436 ZoneList<InstructionOperand*> pointer_operands_; |
432 ZoneList<InstructionOperand*> untagged_operands_; | 437 ZoneList<InstructionOperand*> untagged_operands_; |
433 int instruction_position_; | 438 int instruction_position_; |
434 }; | 439 }; |
435 | 440 |
436 std::ostream& operator<<(std::ostream& os, const PointerMap& pm); | 441 std::ostream& operator<<(std::ostream& os, const PointerMap& pm); |
437 | 442 |
438 // TODO(titzer): s/PointerMap/ReferenceMap/ | 443 // TODO(titzer): s/PointerMap/ReferenceMap/ |
439 class Instruction : public ZoneObject { | 444 class Instruction { |
440 public: | 445 public: |
441 size_t OutputCount() const { return OutputCountField::decode(bit_field_); } | 446 size_t OutputCount() const { return OutputCountField::decode(bit_field_); } |
442 const InstructionOperand* OutputAt(size_t i) const { | 447 const InstructionOperand* OutputAt(size_t i) const { |
443 DCHECK(i < OutputCount()); | 448 DCHECK(i < OutputCount()); |
444 return &operands_[i]; | 449 return &operands_[i]; |
445 } | 450 } |
446 InstructionOperand* OutputAt(size_t i) { | 451 InstructionOperand* OutputAt(size_t i) { |
447 DCHECK(i < OutputCount()); | 452 DCHECK(i < OutputCount()); |
448 return &operands_[i]; | 453 return &operands_[i]; |
449 } | 454 } |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
528 bool ClobbersTemps() const { return IsCall(); } | 533 bool ClobbersTemps() const { return IsCall(); } |
529 bool ClobbersDoubleRegisters() const { return IsCall(); } | 534 bool ClobbersDoubleRegisters() const { return IsCall(); } |
530 PointerMap* pointer_map() const { return pointer_map_; } | 535 PointerMap* pointer_map() const { return pointer_map_; } |
531 | 536 |
532 void set_pointer_map(PointerMap* map) { | 537 void set_pointer_map(PointerMap* map) { |
533 DCHECK(NeedsPointerMap()); | 538 DCHECK(NeedsPointerMap()); |
534 DCHECK(!pointer_map_); | 539 DCHECK(!pointer_map_); |
535 pointer_map_ = map; | 540 pointer_map_ = map; |
536 } | 541 } |
537 | 542 |
538 // Placement new operator so that we can smash instructions into | |
539 // zone-allocated memory. | |
540 void* operator new(size_t, void* location) { return location; } | |
541 | |
542 void operator delete(void* pointer, void* location) { UNREACHABLE(); } | |
543 | |
544 void OverwriteWithNop() { | 543 void OverwriteWithNop() { |
545 opcode_ = ArchOpcodeField::encode(kArchNop); | 544 opcode_ = ArchOpcodeField::encode(kArchNop); |
546 bit_field_ = 0; | 545 bit_field_ = 0; |
547 pointer_map_ = NULL; | 546 pointer_map_ = NULL; |
548 } | 547 } |
549 | 548 |
550 bool IsNop() const { | 549 bool IsNop() const { |
551 return arch_opcode() == kArchNop && InputCount() == 0 && | 550 return arch_opcode() == kArchNop && InputCount() == 0 && |
552 OutputCount() == 0 && TempCount() == 0; | 551 OutputCount() == 0 && TempCount() == 0; |
553 } | 552 } |
554 | 553 |
555 protected: | 554 protected: |
556 explicit Instruction(InstructionCode opcode); | 555 explicit Instruction(InstructionCode opcode); |
557 Instruction(InstructionCode opcode, size_t output_count, | 556 Instruction(InstructionCode opcode, size_t output_count, |
558 InstructionOperand* outputs, size_t input_count, | 557 InstructionOperand* outputs, size_t input_count, |
559 InstructionOperand* inputs, size_t temp_count, | 558 InstructionOperand* inputs, size_t temp_count, |
560 InstructionOperand* temps); | 559 InstructionOperand* temps); |
561 | 560 |
562 protected: | |
563 typedef BitField<size_t, 0, 8> OutputCountField; | 561 typedef BitField<size_t, 0, 8> OutputCountField; |
564 typedef BitField<size_t, 8, 16> InputCountField; | 562 typedef BitField<size_t, 8, 16> InputCountField; |
565 typedef BitField<size_t, 24, 6> TempCountField; | 563 typedef BitField<size_t, 24, 6> TempCountField; |
566 typedef BitField<bool, 30, 1> IsCallField; | 564 typedef BitField<bool, 30, 1> IsCallField; |
567 typedef BitField<bool, 31, 1> IsControlField; | 565 typedef BitField<bool, 31, 1> IsControlField; |
568 | 566 |
569 InstructionCode opcode_; | 567 InstructionCode opcode_; |
570 uint32_t bit_field_; | 568 uint32_t bit_field_; |
571 PointerMap* pointer_map_; | 569 PointerMap* pointer_map_; |
572 InstructionOperand operands_[1]; | 570 InstructionOperand operands_[1]; |
| 571 |
| 572 private: |
| 573 DISALLOW_COPY_AND_ASSIGN(Instruction); |
573 }; | 574 }; |
574 | 575 |
575 | 576 |
576 struct PrintableInstruction { | 577 struct PrintableInstruction { |
577 const RegisterConfiguration* register_configuration_; | 578 const RegisterConfiguration* register_configuration_; |
578 const Instruction* instr_; | 579 const Instruction* instr_; |
579 }; | 580 }; |
580 std::ostream& operator<<(std::ostream& os, const PrintableInstruction& instr); | 581 std::ostream& operator<<(std::ostream& os, const PrintableInstruction& instr); |
581 | 582 |
582 | 583 |
(...skipping 467 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1050 | 1051 |
1051 | 1052 |
1052 std::ostream& operator<<(std::ostream& os, | 1053 std::ostream& operator<<(std::ostream& os, |
1053 const PrintableInstructionSequence& code); | 1054 const PrintableInstructionSequence& code); |
1054 | 1055 |
1055 } // namespace compiler | 1056 } // namespace compiler |
1056 } // namespace internal | 1057 } // namespace internal |
1057 } // namespace v8 | 1058 } // namespace v8 |
1058 | 1059 |
1059 #endif // V8_COMPILER_INSTRUCTION_H_ | 1060 #endif // V8_COMPILER_INSTRUCTION_H_ |
OLD | NEW |