| 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> |
| 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/schedule.h" | 18 #include "src/compiler/schedule.h" |
| 19 #include "src/compiler/source-position.h" | 19 #include "src/compiler/source-position.h" |
| 20 #include "src/zone-allocator.h" | 20 #include "src/zone-allocator.h" |
| 21 | 21 |
| 22 namespace v8 { | 22 namespace v8 { |
| 23 namespace internal { | 23 namespace internal { |
| 24 namespace compiler { | 24 namespace compiler { |
| 25 | 25 |
| 26 // A couple of reserved opcodes are used for internal use. | 26 // A couple of reserved opcodes are used for internal use. |
| 27 const InstructionCode kGapInstruction = -1; | 27 const InstructionCode kGapInstruction = -1; |
| 28 const InstructionCode kSourcePositionInstruction = -2; | 28 const InstructionCode kSourcePositionInstruction = -2; |
| 29 | 29 |
| 30 #define INSTRUCTION_OPERAND_LIST(V) \ | 30 #define INSTRUCTION_OPERAND_LIST(V) \ |
| 31 V(Constant, CONSTANT, 0) \ | 31 V(Constant, CONSTANT) \ |
| 32 V(Immediate, IMMEDIATE, 0) \ | 32 V(Immediate, IMMEDIATE) \ |
| 33 V(StackSlot, STACK_SLOT, 128) \ | 33 V(StackSlot, STACK_SLOT) \ |
| 34 V(DoubleStackSlot, DOUBLE_STACK_SLOT, 128) \ | 34 V(DoubleStackSlot, DOUBLE_STACK_SLOT) \ |
| 35 V(Register, REGISTER, RegisterConfiguration::kMaxGeneralRegisters) \ | 35 V(Register, REGISTER) \ |
| 36 V(DoubleRegister, DOUBLE_REGISTER, RegisterConfiguration::kMaxDoubleRegisters) | 36 V(DoubleRegister, DOUBLE_REGISTER) |
| 37 | 37 |
| 38 class InstructionOperand { | 38 class InstructionOperand { |
| 39 public: | 39 public: |
| 40 static const int kInvalidVirtualRegister = -1; | 40 static const int kInvalidVirtualRegister = -1; |
| 41 | 41 |
| 42 enum Kind { | 42 enum Kind { |
| 43 INVALID, | 43 INVALID, |
| 44 UNALLOCATED, | 44 UNALLOCATED, |
| 45 CONSTANT, | 45 CONSTANT, |
| 46 IMMEDIATE, | 46 IMMEDIATE, |
| 47 STACK_SLOT, | 47 STACK_SLOT, |
| 48 DOUBLE_STACK_SLOT, | 48 DOUBLE_STACK_SLOT, |
| 49 REGISTER, | 49 REGISTER, |
| 50 DOUBLE_REGISTER | 50 DOUBLE_REGISTER |
| 51 }; | 51 }; |
| 52 | 52 |
| 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 Kind kind() const { return KindField::decode(value_); } | 63 Kind kind() const { return KindField::decode(value_); } |
| 64 int index() const { return static_cast<int>(value_) >> KindField::kSize; } | 64 int index() const { return static_cast<int>(value_) >> KindField::kSize; } |
| 65 #define INSTRUCTION_OPERAND_PREDICATE(name, type, number) \ | 65 #define INSTRUCTION_OPERAND_PREDICATE(name, type) \ |
| 66 bool Is##name() const { return kind() == type; } | 66 bool Is##name() const { return kind() == type; } |
| 67 INSTRUCTION_OPERAND_LIST(INSTRUCTION_OPERAND_PREDICATE) | 67 INSTRUCTION_OPERAND_LIST(INSTRUCTION_OPERAND_PREDICATE) |
| 68 INSTRUCTION_OPERAND_PREDICATE(Unallocated, UNALLOCATED, 0) | 68 INSTRUCTION_OPERAND_PREDICATE(Unallocated, UNALLOCATED) |
| 69 INSTRUCTION_OPERAND_PREDICATE(Invalid, INVALID, 0) | 69 INSTRUCTION_OPERAND_PREDICATE(Invalid, INVALID) |
| 70 #undef INSTRUCTION_OPERAND_PREDICATE | 70 #undef INSTRUCTION_OPERAND_PREDICATE |
| 71 bool Equals(const InstructionOperand* other) const { | 71 bool Equals(const InstructionOperand* other) const { |
| 72 return value_ == other->value_; | 72 return value_ == other->value_; |
| 73 } | 73 } |
| 74 | 74 |
| 75 void ConvertTo(Kind kind, int index) { | 75 void ConvertTo(Kind kind, int index) { |
| 76 if (kind == REGISTER || kind == DOUBLE_REGISTER) DCHECK(index >= 0); | 76 if (kind == REGISTER || kind == DOUBLE_REGISTER) DCHECK(index >= 0); |
| 77 value_ = KindField::encode(kind); | 77 value_ = KindField::encode(kind); |
| 78 value_ |= bit_cast<unsigned>(index << KindField::kSize); | 78 value_ |= bit_cast<unsigned>(index << KindField::kSize); |
| 79 DCHECK(this->index() == index); | 79 DCHECK(this->index() == index); |
| 80 if (kind != UNALLOCATED) virtual_register_ = kInvalidVirtualRegister; | 80 if (kind != UNALLOCATED) virtual_register_ = kInvalidVirtualRegister; |
| 81 } | 81 } |
| 82 | 82 |
| 83 // Calls SetUpCache()/TearDownCache() for each subclass. | |
| 84 static void SetUpCaches(); | |
| 85 static void TearDownCaches(); | |
| 86 | |
| 87 // TODO(dcarney): get rid of these | 83 // TODO(dcarney): get rid of these |
| 88 void* operator new(size_t, void* location) { return location; } | 84 void* operator new(size_t, void* location) { return location; } |
| 89 void* operator new(size_t size, Zone* zone) { | 85 void* operator new(size_t size, Zone* zone) { |
| 90 return zone->New(static_cast<int>(size)); | 86 return zone->New(static_cast<int>(size)); |
| 91 } | 87 } |
| 92 void operator delete(void* pointer, Zone* zone) { UNREACHABLE(); } | 88 void operator delete(void* pointer, Zone* zone) { UNREACHABLE(); } |
| 93 | 89 |
| 94 protected: | 90 protected: |
| 95 InstructionOperand(Kind kind, int index, int virtual_register) | 91 InstructionOperand(Kind kind, int index, int virtual_register) |
| 96 : virtual_register_(virtual_register) { | 92 : virtual_register_(virtual_register) { |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 131 // to some other operand used inside instruction (i.e. temporary or | 127 // to some other operand used inside instruction (i.e. temporary or |
| 132 // output). | 128 // output). |
| 133 USED_AT_START, | 129 USED_AT_START, |
| 134 | 130 |
| 135 // 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 |
| 136 // instruction. This means that register allocator will not reuse it's | 132 // instruction. This means that register allocator will not reuse it's |
| 137 // register for any other operand inside instruction. | 133 // register for any other operand inside instruction. |
| 138 USED_AT_END | 134 USED_AT_END |
| 139 }; | 135 }; |
| 140 | 136 |
| 141 // TODO(dcarney): remove this. | |
| 142 static const int kInvalidVirtualRegister = -1; | |
| 143 | |
| 144 UnallocatedOperand(ExtendedPolicy policy, int virtual_register) | 137 UnallocatedOperand(ExtendedPolicy policy, int virtual_register) |
| 145 : InstructionOperand(UNALLOCATED, 0, virtual_register) { | 138 : InstructionOperand(UNALLOCATED, 0, virtual_register) { |
| 146 value_ |= BasicPolicyField::encode(EXTENDED_POLICY); | 139 value_ |= BasicPolicyField::encode(EXTENDED_POLICY); |
| 147 value_ |= ExtendedPolicyField::encode(policy); | 140 value_ |= ExtendedPolicyField::encode(policy); |
| 148 value_ |= LifetimeField::encode(USED_AT_END); | 141 value_ |= LifetimeField::encode(USED_AT_END); |
| 149 } | 142 } |
| 150 | 143 |
| 151 UnallocatedOperand(BasicPolicy policy, int index, int virtual_register) | 144 UnallocatedOperand(BasicPolicy policy, int index, int virtual_register) |
| 152 : InstructionOperand(UNALLOCATED, 0, virtual_register) { | 145 : InstructionOperand(UNALLOCATED, 0, virtual_register) { |
| 153 DCHECK(policy == FIXED_SLOT); | 146 DCHECK(policy == FIXED_SLOT); |
| (...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 342 | 335 |
| 343 struct PrintableMoveOperands { | 336 struct PrintableMoveOperands { |
| 344 const RegisterConfiguration* register_configuration_; | 337 const RegisterConfiguration* register_configuration_; |
| 345 const MoveOperands* move_operands_; | 338 const MoveOperands* move_operands_; |
| 346 }; | 339 }; |
| 347 | 340 |
| 348 | 341 |
| 349 std::ostream& operator<<(std::ostream& os, const PrintableMoveOperands& mo); | 342 std::ostream& operator<<(std::ostream& os, const PrintableMoveOperands& mo); |
| 350 | 343 |
| 351 | 344 |
| 352 template <InstructionOperand::Kind kOperandKind, int kNumCachedOperands> | 345 #define INSTRUCTION_SUBKIND_OPERAND_CLASS(SubKind, kOperandKind) \ |
| 353 class SubKindOperand FINAL : public InstructionOperand { | 346 class SubKind##Operand FINAL : public InstructionOperand { \ |
| 354 public: | 347 public: \ |
| 355 explicit SubKindOperand(int index) | 348 explicit SubKind##Operand(int index) \ |
| 356 : InstructionOperand(kOperandKind, index) {} | 349 : InstructionOperand(kOperandKind, index) {} \ |
| 357 | 350 \ |
| 358 static SubKindOperand* Create(int index, Zone* zone) { | 351 static SubKind##Operand* New(int index, Zone* zone) { \ |
| 359 DCHECK(index >= 0); | 352 return new (zone) SubKind##Operand(index); \ |
| 360 if (index < kNumCachedOperands) return &cache[index]; | 353 } \ |
| 361 return new (zone) SubKindOperand(index); | 354 \ |
| 362 } | 355 static SubKind##Operand* cast(InstructionOperand* op) { \ |
| 363 | 356 DCHECK(op->kind() == kOperandKind); \ |
| 364 static SubKindOperand* cast(InstructionOperand* op) { | 357 return reinterpret_cast<SubKind##Operand*>(op); \ |
| 365 DCHECK(op->kind() == kOperandKind); | 358 } \ |
| 366 return reinterpret_cast<SubKindOperand*>(op); | 359 \ |
| 367 } | 360 static const SubKind##Operand* cast(const InstructionOperand* op) { \ |
| 368 | 361 DCHECK(op->kind() == kOperandKind); \ |
| 369 static const SubKindOperand* cast(const InstructionOperand* op) { | 362 return reinterpret_cast<const SubKind##Operand*>(op); \ |
| 370 DCHECK(op->kind() == kOperandKind); | 363 } \ |
| 371 return reinterpret_cast<const SubKindOperand*>(op); | 364 \ |
| 372 } | 365 static SubKind##Operand cast(const InstructionOperand& op) { \ |
| 373 | 366 DCHECK(op.kind() == kOperandKind); \ |
| 374 static SubKindOperand cast(const InstructionOperand& op) { | 367 return *static_cast<const SubKind##Operand*>(&op); \ |
| 375 DCHECK(op.kind() == kOperandKind); | 368 } \ |
| 376 return *static_cast<const SubKindOperand*>(&op); | 369 }; |
| 377 } | 370 INSTRUCTION_OPERAND_LIST(INSTRUCTION_SUBKIND_OPERAND_CLASS) |
| 378 | 371 #undef INSTRUCTION_SUBKIND_OPERAND_CLASS |
| 379 static void SetUpCache(); | |
| 380 static void TearDownCache(); | |
| 381 | |
| 382 private: | |
| 383 static SubKindOperand* cache; | |
| 384 | |
| 385 SubKindOperand() : InstructionOperand(kOperandKind, 0) {} // For the caches. | |
| 386 }; | |
| 387 | |
| 388 | |
| 389 #define INSTRUCTION_TYPEDEF_SUBKIND_OPERAND_CLASS(name, type, number) \ | |
| 390 typedef SubKindOperand<InstructionOperand::type, number> name##Operand; | |
| 391 INSTRUCTION_OPERAND_LIST(INSTRUCTION_TYPEDEF_SUBKIND_OPERAND_CLASS) | |
| 392 #undef INSTRUCTION_TYPEDEF_SUBKIND_OPERAND_CLASS | |
| 393 | 372 |
| 394 | 373 |
| 395 class ParallelMove FINAL : public ZoneObject { | 374 class ParallelMove FINAL : public ZoneObject { |
| 396 public: | 375 public: |
| 397 explicit ParallelMove(Zone* zone) : move_operands_(4, zone) {} | 376 explicit ParallelMove(Zone* zone) : move_operands_(4, zone) {} |
| 398 | 377 |
| 399 void AddMove(InstructionOperand* from, InstructionOperand* to, Zone* zone) { | 378 void AddMove(InstructionOperand* from, InstructionOperand* to, Zone* zone) { |
| 400 move_operands_.Add(MoveOperands(from, to), zone); | 379 move_operands_.Add(MoveOperands(from, to), zone); |
| 401 } | 380 } |
| 402 | 381 |
| (...skipping 682 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1085 | 1064 |
| 1086 | 1065 |
| 1087 std::ostream& operator<<(std::ostream& os, | 1066 std::ostream& operator<<(std::ostream& os, |
| 1088 const PrintableInstructionSequence& code); | 1067 const PrintableInstructionSequence& code); |
| 1089 | 1068 |
| 1090 } // namespace compiler | 1069 } // namespace compiler |
| 1091 } // namespace internal | 1070 } // namespace internal |
| 1092 } // namespace v8 | 1071 } // namespace v8 |
| 1093 | 1072 |
| 1094 #endif // V8_COMPILER_INSTRUCTION_H_ | 1073 #endif // V8_COMPILER_INSTRUCTION_H_ |
| OLD | NEW |