PageRenderTime 35ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/test/unittests/compiler/instruction-selector-unittest.h

https://gitlab.com/AnneSmile/v8
C Header | 300 lines | 244 code | 50 blank | 6 comment | 12 complexity | d7948b5323f33ecc44d2f933e0f6ac6a MD5 | raw file
  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
  3. // found in the LICENSE file.
  4. #ifndef V8_UNITTESTS_COMPILER_INSTRUCTION_SELECTOR_UNITTEST_H_
  5. #define V8_UNITTESTS_COMPILER_INSTRUCTION_SELECTOR_UNITTEST_H_
  6. #include <deque>
  7. #include <set>
  8. #include "src/base/utils/random-number-generator.h"
  9. #include "src/compiler/instruction-selector.h"
  10. #include "src/compiler/raw-machine-assembler.h"
  11. #include "src/macro-assembler.h"
  12. #include "test/unittests/test-utils.h"
  13. namespace v8 {
  14. namespace internal {
  15. namespace compiler {
  16. class InstructionSelectorTest : public TestWithContext,
  17. public TestWithIsolateAndZone {
  18. public:
  19. InstructionSelectorTest();
  20. ~InstructionSelectorTest() override;
  21. base::RandomNumberGenerator* rng() { return &rng_; }
  22. class Stream;
  23. enum StreamBuilderMode {
  24. kAllInstructions,
  25. kTargetInstructions,
  26. kAllExceptNopInstructions
  27. };
  28. class StreamBuilder final : public RawMachineAssembler {
  29. public:
  30. StreamBuilder(InstructionSelectorTest* test, MachineType return_type)
  31. : RawMachineAssembler(test->isolate(),
  32. new (test->zone()) Graph(test->zone()),
  33. MakeCallDescriptor(test->zone(), return_type),
  34. MachineType::PointerRepresentation(),
  35. MachineOperatorBuilder::kAllOptionalOps),
  36. test_(test) {}
  37. StreamBuilder(InstructionSelectorTest* test, MachineType return_type,
  38. MachineType parameter0_type)
  39. : RawMachineAssembler(
  40. test->isolate(), new (test->zone()) Graph(test->zone()),
  41. MakeCallDescriptor(test->zone(), return_type, parameter0_type),
  42. MachineType::PointerRepresentation(),
  43. MachineOperatorBuilder::kAllOptionalOps),
  44. test_(test) {}
  45. StreamBuilder(InstructionSelectorTest* test, MachineType return_type,
  46. MachineType parameter0_type, MachineType parameter1_type)
  47. : RawMachineAssembler(
  48. test->isolate(), new (test->zone()) Graph(test->zone()),
  49. MakeCallDescriptor(test->zone(), return_type, parameter0_type,
  50. parameter1_type),
  51. MachineType::PointerRepresentation(),
  52. MachineOperatorBuilder::kAllOptionalOps),
  53. test_(test) {}
  54. StreamBuilder(InstructionSelectorTest* test, MachineType return_type,
  55. MachineType parameter0_type, MachineType parameter1_type,
  56. MachineType parameter2_type)
  57. : RawMachineAssembler(
  58. test->isolate(), new (test->zone()) Graph(test->zone()),
  59. MakeCallDescriptor(test->zone(), return_type, parameter0_type,
  60. parameter1_type, parameter2_type),
  61. MachineType::PointerRepresentation(),
  62. MachineOperatorBuilder::kAllOptionalOps),
  63. test_(test) {}
  64. Stream Build(CpuFeature feature) {
  65. return Build(InstructionSelector::Features(feature));
  66. }
  67. Stream Build(CpuFeature feature1, CpuFeature feature2) {
  68. return Build(InstructionSelector::Features(feature1, feature2));
  69. }
  70. Stream Build(StreamBuilderMode mode = kTargetInstructions) {
  71. return Build(InstructionSelector::Features(), mode);
  72. }
  73. Stream Build(InstructionSelector::Features features,
  74. StreamBuilderMode mode = kTargetInstructions,
  75. InstructionSelector::SourcePositionMode source_position_mode =
  76. InstructionSelector::kAllSourcePositions);
  77. const FrameStateFunctionInfo* GetFrameStateFunctionInfo(int parameter_count,
  78. int local_count);
  79. private:
  80. CallDescriptor* MakeCallDescriptor(Zone* zone, MachineType return_type) {
  81. MachineSignature::Builder builder(zone, 1, 0);
  82. builder.AddReturn(return_type);
  83. return MakeSimpleCallDescriptor(zone, builder.Build());
  84. }
  85. CallDescriptor* MakeCallDescriptor(Zone* zone, MachineType return_type,
  86. MachineType parameter0_type) {
  87. MachineSignature::Builder builder(zone, 1, 1);
  88. builder.AddReturn(return_type);
  89. builder.AddParam(parameter0_type);
  90. return MakeSimpleCallDescriptor(zone, builder.Build());
  91. }
  92. CallDescriptor* MakeCallDescriptor(Zone* zone, MachineType return_type,
  93. MachineType parameter0_type,
  94. MachineType parameter1_type) {
  95. MachineSignature::Builder builder(zone, 1, 2);
  96. builder.AddReturn(return_type);
  97. builder.AddParam(parameter0_type);
  98. builder.AddParam(parameter1_type);
  99. return MakeSimpleCallDescriptor(zone, builder.Build());
  100. }
  101. CallDescriptor* MakeCallDescriptor(Zone* zone, MachineType return_type,
  102. MachineType parameter0_type,
  103. MachineType parameter1_type,
  104. MachineType parameter2_type) {
  105. MachineSignature::Builder builder(zone, 1, 3);
  106. builder.AddReturn(return_type);
  107. builder.AddParam(parameter0_type);
  108. builder.AddParam(parameter1_type);
  109. builder.AddParam(parameter2_type);
  110. return MakeSimpleCallDescriptor(zone, builder.Build());
  111. }
  112. private:
  113. InstructionSelectorTest* test_;
  114. // Create a simple call descriptor for testing.
  115. CallDescriptor* MakeSimpleCallDescriptor(Zone* zone,
  116. MachineSignature* msig) {
  117. LocationSignature::Builder locations(zone, msig->return_count(),
  118. msig->parameter_count());
  119. // Add return location(s).
  120. const int return_count = static_cast<int>(msig->return_count());
  121. for (int i = 0; i < return_count; i++) {
  122. locations.AddReturn(
  123. LinkageLocation::ForCallerFrameSlot(-1 - i, msig->GetReturn(i)));
  124. }
  125. // Just put all parameters on the stack.
  126. const int parameter_count = static_cast<int>(msig->parameter_count());
  127. for (int i = 0; i < parameter_count; i++) {
  128. locations.AddParam(
  129. LinkageLocation::ForCallerFrameSlot(-1 - i, msig->GetParam(i)));
  130. }
  131. const RegList kCalleeSaveRegisters = 0;
  132. const RegList kCalleeSaveFPRegisters = 0;
  133. MachineType target_type = MachineType::Pointer();
  134. LinkageLocation target_loc = LinkageLocation::ForAnyRegister();
  135. return new (zone) CallDescriptor( // --
  136. CallDescriptor::kCallAddress, // kind
  137. target_type, // target MachineType
  138. target_loc, // target location
  139. locations.Build(), // location_sig
  140. 0, // stack_parameter_count
  141. Operator::kNoProperties, // properties
  142. kCalleeSaveRegisters, // callee-saved registers
  143. kCalleeSaveFPRegisters, // callee-saved fp regs
  144. CallDescriptor::kNoFlags, // flags
  145. "iselect-test-call");
  146. }
  147. };
  148. class Stream final {
  149. public:
  150. size_t size() const { return instructions_.size(); }
  151. const Instruction* operator[](size_t index) const {
  152. EXPECT_LT(index, size());
  153. return instructions_[index];
  154. }
  155. bool IsDouble(const InstructionOperand* operand) const {
  156. return IsDouble(ToVreg(operand));
  157. }
  158. bool IsDouble(const Node* node) const { return IsDouble(ToVreg(node)); }
  159. bool IsInteger(const InstructionOperand* operand) const {
  160. return IsInteger(ToVreg(operand));
  161. }
  162. bool IsInteger(const Node* node) const { return IsInteger(ToVreg(node)); }
  163. bool IsReference(const InstructionOperand* operand) const {
  164. return IsReference(ToVreg(operand));
  165. }
  166. bool IsReference(const Node* node) const {
  167. return IsReference(ToVreg(node));
  168. }
  169. float ToFloat32(const InstructionOperand* operand) const {
  170. return ToConstant(operand).ToFloat32();
  171. }
  172. double ToFloat64(const InstructionOperand* operand) const {
  173. return ToConstant(operand).ToFloat64();
  174. }
  175. int32_t ToInt32(const InstructionOperand* operand) const {
  176. return ToConstant(operand).ToInt32();
  177. }
  178. int64_t ToInt64(const InstructionOperand* operand) const {
  179. return ToConstant(operand).ToInt64();
  180. }
  181. Handle<HeapObject> ToHeapObject(const InstructionOperand* operand) const {
  182. return ToConstant(operand).ToHeapObject();
  183. }
  184. int ToVreg(const InstructionOperand* operand) const {
  185. if (operand->IsConstant()) {
  186. return ConstantOperand::cast(operand)->virtual_register();
  187. }
  188. EXPECT_EQ(InstructionOperand::UNALLOCATED, operand->kind());
  189. return UnallocatedOperand::cast(operand)->virtual_register();
  190. }
  191. int ToVreg(const Node* node) const;
  192. bool IsFixed(const InstructionOperand* operand, Register reg) const;
  193. bool IsSameAsFirst(const InstructionOperand* operand) const;
  194. bool IsUsedAtStart(const InstructionOperand* operand) const;
  195. FrameStateDescriptor* GetFrameStateDescriptor(int deoptimization_id) {
  196. EXPECT_LT(deoptimization_id, GetFrameStateDescriptorCount());
  197. return deoptimization_entries_[deoptimization_id];
  198. }
  199. int GetFrameStateDescriptorCount() {
  200. return static_cast<int>(deoptimization_entries_.size());
  201. }
  202. private:
  203. bool IsDouble(int virtual_register) const {
  204. return doubles_.find(virtual_register) != doubles_.end();
  205. }
  206. bool IsInteger(int virtual_register) const {
  207. return !IsDouble(virtual_register) && !IsReference(virtual_register);
  208. }
  209. bool IsReference(int virtual_register) const {
  210. return references_.find(virtual_register) != references_.end();
  211. }
  212. Constant ToConstant(const InstructionOperand* operand) const {
  213. ConstantMap::const_iterator i;
  214. if (operand->IsConstant()) {
  215. i = constants_.find(ConstantOperand::cast(operand)->virtual_register());
  216. EXPECT_EQ(ConstantOperand::cast(operand)->virtual_register(), i->first);
  217. EXPECT_FALSE(constants_.end() == i);
  218. } else {
  219. EXPECT_EQ(InstructionOperand::IMMEDIATE, operand->kind());
  220. auto imm = ImmediateOperand::cast(operand);
  221. if (imm->type() == ImmediateOperand::INLINE) {
  222. return Constant(imm->inline_value());
  223. }
  224. i = immediates_.find(imm->indexed_value());
  225. EXPECT_EQ(imm->indexed_value(), i->first);
  226. EXPECT_FALSE(immediates_.end() == i);
  227. }
  228. return i->second;
  229. }
  230. friend class StreamBuilder;
  231. typedef std::map<int, Constant> ConstantMap;
  232. typedef std::map<NodeId, int> VirtualRegisters;
  233. ConstantMap constants_;
  234. ConstantMap immediates_;
  235. std::deque<Instruction*> instructions_;
  236. std::set<int> doubles_;
  237. std::set<int> references_;
  238. VirtualRegisters virtual_registers_;
  239. std::deque<FrameStateDescriptor*> deoptimization_entries_;
  240. };
  241. base::RandomNumberGenerator rng_;
  242. };
  243. template <typename T>
  244. class InstructionSelectorTestWithParam
  245. : public InstructionSelectorTest,
  246. public ::testing::WithParamInterface<T> {};
  247. } // namespace compiler
  248. } // namespace internal
  249. } // namespace v8
  250. #endif // V8_UNITTESTS_COMPILER_INSTRUCTION_SELECTOR_UNITTEST_H_