| 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 #include "src/compiler/gap-resolver.h" | 5 #include "src/compiler/gap-resolver.h" |
| 6 | 6 |
| 7 #include "src/base/utils/random-number-generator.h" | 7 #include "src/base/utils/random-number-generator.h" |
| 8 #include "test/cctest/cctest.h" | 8 #include "test/cctest/cctest.h" |
| 9 | 9 |
| 10 using namespace v8::internal; | 10 using namespace v8::internal; |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 44 | 44 |
| 45 void write(const InstructionOperand* op, Value v) { | 45 void write(const InstructionOperand* op, Value v) { |
| 46 if (v == ValueFor(op)) { | 46 if (v == ValueFor(op)) { |
| 47 values_.erase(KeyFor(op)); | 47 values_.erase(KeyFor(op)); |
| 48 } else { | 48 } else { |
| 49 values_[KeyFor(op)] = v; | 49 values_[KeyFor(op)] = v; |
| 50 } | 50 } |
| 51 } | 51 } |
| 52 | 52 |
| 53 static Key KeyFor(const InstructionOperand* op) { | 53 static Key KeyFor(const InstructionOperand* op) { |
| 54 return Key(op->kind(), op->index()); | 54 int v = op->IsConstant() ? ConstantOperand::cast(op)->virtual_register() |
| 55 : AllocatedOperand::cast(op)->index(); |
| 56 return Key(op->kind(), v); |
| 55 } | 57 } |
| 56 | 58 |
| 57 static Value ValueFor(const InstructionOperand* op) { | 59 static Value ValueFor(const InstructionOperand* op) { |
| 58 return Value(op->kind(), op->index()); | 60 int v = op->IsConstant() ? ConstantOperand::cast(op)->virtual_register() |
| 61 : AllocatedOperand::cast(op)->index(); |
| 62 return Value(op->kind(), v); |
| 63 } |
| 64 |
| 65 static InstructionOperand FromKey(Key key) { |
| 66 if (key.first == InstructionOperand::CONSTANT) { |
| 67 return ConstantOperand(key.second); |
| 68 } |
| 69 return AllocatedOperand(key.first, key.second); |
| 59 } | 70 } |
| 60 | 71 |
| 61 friend std::ostream& operator<<(std::ostream& os, | 72 friend std::ostream& operator<<(std::ostream& os, |
| 62 const InterpreterState& is) { | 73 const InterpreterState& is) { |
| 63 for (OperandMap::const_iterator it = is.values_.begin(); | 74 for (OperandMap::const_iterator it = is.values_.begin(); |
| 64 it != is.values_.end(); ++it) { | 75 it != is.values_.end(); ++it) { |
| 65 if (it != is.values_.begin()) os << " "; | 76 if (it != is.values_.begin()) os << " "; |
| 66 InstructionOperand source(it->first.first, it->first.second); | 77 InstructionOperand source = FromKey(it->first); |
| 67 InstructionOperand destination(it->second.first, it->second.second); | 78 InstructionOperand destination = FromKey(it->second); |
| 68 MoveOperands mo(&source, &destination); | 79 MoveOperands mo(&source, &destination); |
| 69 PrintableMoveOperands pmo = {RegisterConfiguration::ArchDefault(), &mo}; | 80 PrintableMoveOperands pmo = {RegisterConfiguration::ArchDefault(), &mo}; |
| 70 os << pmo; | 81 os << pmo; |
| 71 } | 82 } |
| 72 return os; | 83 return os; |
| 73 } | 84 } |
| 74 | 85 |
| 75 OperandMap values_; | 86 OperandMap values_; |
| 76 }; | 87 }; |
| 77 | 88 |
| (...skipping 30 matching lines...) Expand all Loading... |
| 108 | 119 |
| 109 | 120 |
| 110 class ParallelMoveCreator : public HandleAndZoneScope { | 121 class ParallelMoveCreator : public HandleAndZoneScope { |
| 111 public: | 122 public: |
| 112 ParallelMoveCreator() : rng_(CcTest::random_number_generator()) {} | 123 ParallelMoveCreator() : rng_(CcTest::random_number_generator()) {} |
| 113 | 124 |
| 114 ParallelMove* Create(int size) { | 125 ParallelMove* Create(int size) { |
| 115 ParallelMove* parallel_move = new (main_zone()) ParallelMove(main_zone()); | 126 ParallelMove* parallel_move = new (main_zone()) ParallelMove(main_zone()); |
| 116 std::set<InstructionOperand*, InstructionOperandComparator> seen; | 127 std::set<InstructionOperand*, InstructionOperandComparator> seen; |
| 117 for (int i = 0; i < size; ++i) { | 128 for (int i = 0; i < size; ++i) { |
| 118 MoveOperands mo(CreateRandomOperand(), CreateRandomOperand()); | 129 MoveOperands mo(CreateRandomOperand(true), CreateRandomOperand(false)); |
| 119 if (!mo.IsRedundant() && seen.find(mo.destination()) == seen.end()) { | 130 if (!mo.IsRedundant() && seen.find(mo.destination()) == seen.end()) { |
| 120 parallel_move->AddMove(mo.source(), mo.destination(), main_zone()); | 131 parallel_move->AddMove(mo.source(), mo.destination(), main_zone()); |
| 121 seen.insert(mo.destination()); | 132 seen.insert(mo.destination()); |
| 122 } | 133 } |
| 123 } | 134 } |
| 124 return parallel_move; | 135 return parallel_move; |
| 125 } | 136 } |
| 126 | 137 |
| 127 private: | 138 private: |
| 128 struct InstructionOperandComparator { | 139 struct InstructionOperandComparator { |
| 129 bool operator()(const InstructionOperand* x, | 140 bool operator()(const InstructionOperand* x, |
| 130 const InstructionOperand* y) const { | 141 const InstructionOperand* y) const { |
| 131 return (x->kind() < y->kind()) || | 142 return *x < *y; |
| 132 (x->kind() == y->kind() && x->index() < y->index()); | |
| 133 } | 143 } |
| 134 }; | 144 }; |
| 135 | 145 |
| 136 InstructionOperand* CreateRandomOperand() { | 146 InstructionOperand* CreateRandomOperand(bool is_source) { |
| 137 int index = rng_->NextInt(6); | 147 int index = rng_->NextInt(6); |
| 138 switch (rng_->NextInt(5)) { | 148 // destination can't be Constant. |
| 149 switch (rng_->NextInt(is_source ? 5 : 4)) { |
| 139 case 0: | 150 case 0: |
| 140 return ConstantOperand::New(index, main_zone()); | 151 return StackSlotOperand::New(main_zone(), index); |
| 141 case 1: | 152 case 1: |
| 142 return StackSlotOperand::New(index, main_zone()); | 153 return DoubleStackSlotOperand::New(main_zone(), index); |
| 143 case 2: | 154 case 2: |
| 144 return DoubleStackSlotOperand::New(index, main_zone()); | 155 return RegisterOperand::New(main_zone(), index); |
| 145 case 3: | 156 case 3: |
| 146 return RegisterOperand::New(index, main_zone()); | 157 return DoubleRegisterOperand::New(main_zone(), index); |
| 147 case 4: | 158 case 4: |
| 148 return DoubleRegisterOperand::New(index, main_zone()); | 159 return ConstantOperand::New(main_zone(), index); |
| 149 } | 160 } |
| 150 UNREACHABLE(); | 161 UNREACHABLE(); |
| 151 return NULL; | 162 return NULL; |
| 152 } | 163 } |
| 153 | 164 |
| 154 private: | 165 private: |
| 155 v8::base::RandomNumberGenerator* rng_; | 166 v8::base::RandomNumberGenerator* rng_; |
| 156 }; | 167 }; |
| 157 | 168 |
| 158 | 169 |
| 159 TEST(FuzzResolver) { | 170 TEST(FuzzResolver) { |
| 160 ParallelMoveCreator pmc; | 171 ParallelMoveCreator pmc; |
| 161 for (int size = 0; size < 20; ++size) { | 172 for (int size = 0; size < 20; ++size) { |
| 162 for (int repeat = 0; repeat < 50; ++repeat) { | 173 for (int repeat = 0; repeat < 50; ++repeat) { |
| 163 ParallelMove* pm = pmc.Create(size); | 174 ParallelMove* pm = pmc.Create(size); |
| 164 | 175 |
| 165 // Note: The gap resolver modifies the ParallelMove, so interpret first. | 176 // Note: The gap resolver modifies the ParallelMove, so interpret first. |
| 166 MoveInterpreter mi1; | 177 MoveInterpreter mi1; |
| 167 mi1.AssembleParallelMove(pm); | 178 mi1.AssembleParallelMove(pm); |
| 168 | 179 |
| 169 MoveInterpreter mi2; | 180 MoveInterpreter mi2; |
| 170 GapResolver resolver(&mi2); | 181 GapResolver resolver(&mi2); |
| 171 resolver.Resolve(pm); | 182 resolver.Resolve(pm); |
| 172 | 183 |
| 173 CHECK(mi1.state() == mi2.state()); | 184 CHECK(mi1.state() == mi2.state()); |
| 174 } | 185 } |
| 175 } | 186 } |
| 176 } | 187 } |
| OLD | NEW |