| 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 |