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/common-operator.h" | 5 #include "src/compiler/common-operator.h" |
6 #include "src/compiler/generic-node-inl.h" | 6 #include "src/compiler/generic-node-inl.h" |
7 #include "src/compiler/graph.h" | 7 #include "src/compiler/graph.h" |
8 #include "src/compiler/instruction.h" | 8 #include "src/compiler/instruction.h" |
9 #include "src/macro-assembler.h" | |
10 | 9 |
11 namespace v8 { | 10 namespace v8 { |
12 namespace internal { | 11 namespace internal { |
13 namespace compiler { | 12 namespace compiler { |
14 | 13 |
15 STATIC_ASSERT(kMaxGeneralRegisters >= Register::kNumRegisters); | 14 std::ostream& operator<<(std::ostream& os, |
16 STATIC_ASSERT(kMaxDoubleRegisters >= DoubleRegister::kMaxNumRegisters); | 15 const PrintableInstructionOperand& printable) { |
17 | 16 const InstructionOperand& op = *printable.op_; |
18 | 17 const RegisterConfiguration* conf = printable.register_configuration_; |
19 std::ostream& operator<<(std::ostream& os, const InstructionOperand& op) { | |
20 switch (op.kind()) { | 18 switch (op.kind()) { |
21 case InstructionOperand::INVALID: | 19 case InstructionOperand::INVALID: |
22 return os << "(0)"; | 20 return os << "(0)"; |
23 case InstructionOperand::UNALLOCATED: { | 21 case InstructionOperand::UNALLOCATED: { |
24 const UnallocatedOperand* unalloc = UnallocatedOperand::cast(&op); | 22 const UnallocatedOperand* unalloc = UnallocatedOperand::cast(&op); |
25 os << "v" << unalloc->virtual_register(); | 23 os << "v" << unalloc->virtual_register(); |
26 if (unalloc->basic_policy() == UnallocatedOperand::FIXED_SLOT) { | 24 if (unalloc->basic_policy() == UnallocatedOperand::FIXED_SLOT) { |
27 return os << "(=" << unalloc->fixed_slot_index() << "S)"; | 25 return os << "(=" << unalloc->fixed_slot_index() << "S)"; |
28 } | 26 } |
29 switch (unalloc->extended_policy()) { | 27 switch (unalloc->extended_policy()) { |
30 case UnallocatedOperand::NONE: | 28 case UnallocatedOperand::NONE: |
31 return os; | 29 return os; |
32 case UnallocatedOperand::FIXED_REGISTER: | 30 case UnallocatedOperand::FIXED_REGISTER: |
33 return os << "(=" << Register::AllocationIndexToString( | 31 return os << "(=" << conf->general_register_name( |
34 unalloc->fixed_register_index()) << ")"; | 32 unalloc->fixed_register_index()) << ")"; |
35 case UnallocatedOperand::FIXED_DOUBLE_REGISTER: | 33 case UnallocatedOperand::FIXED_DOUBLE_REGISTER: |
36 return os << "(=" << DoubleRegister::AllocationIndexToString( | 34 return os << "(=" << conf->double_register_name( |
37 unalloc->fixed_register_index()) << ")"; | 35 unalloc->fixed_register_index()) << ")"; |
38 case UnallocatedOperand::MUST_HAVE_REGISTER: | 36 case UnallocatedOperand::MUST_HAVE_REGISTER: |
39 return os << "(R)"; | 37 return os << "(R)"; |
40 case UnallocatedOperand::SAME_AS_FIRST_INPUT: | 38 case UnallocatedOperand::SAME_AS_FIRST_INPUT: |
41 return os << "(1)"; | 39 return os << "(1)"; |
42 case UnallocatedOperand::ANY: | 40 case UnallocatedOperand::ANY: |
43 return os << "(-)"; | 41 return os << "(-)"; |
44 } | 42 } |
45 } | 43 } |
46 case InstructionOperand::CONSTANT: | 44 case InstructionOperand::CONSTANT: |
47 return os << "[constant:" << op.index() << "]"; | 45 return os << "[constant:" << op.index() << "]"; |
48 case InstructionOperand::IMMEDIATE: | 46 case InstructionOperand::IMMEDIATE: |
49 return os << "[immediate:" << op.index() << "]"; | 47 return os << "[immediate:" << op.index() << "]"; |
50 case InstructionOperand::STACK_SLOT: | 48 case InstructionOperand::STACK_SLOT: |
51 return os << "[stack:" << op.index() << "]"; | 49 return os << "[stack:" << op.index() << "]"; |
52 case InstructionOperand::DOUBLE_STACK_SLOT: | 50 case InstructionOperand::DOUBLE_STACK_SLOT: |
53 return os << "[double_stack:" << op.index() << "]"; | 51 return os << "[double_stack:" << op.index() << "]"; |
54 case InstructionOperand::REGISTER: | 52 case InstructionOperand::REGISTER: |
55 return os << "[" << Register::AllocationIndexToString(op.index()) | 53 return os << "[" << conf->general_register_name(op.index()) << "|R]"; |
56 << "|R]"; | |
57 case InstructionOperand::DOUBLE_REGISTER: | 54 case InstructionOperand::DOUBLE_REGISTER: |
58 return os << "[" << DoubleRegister::AllocationIndexToString(op.index()) | 55 return os << "[" << conf->double_register_name(op.index()) << "|R]"; |
59 << "|R]"; | |
60 } | 56 } |
61 UNREACHABLE(); | 57 UNREACHABLE(); |
62 return os; | 58 return os; |
63 } | 59 } |
64 | 60 |
65 | 61 |
66 template <InstructionOperand::Kind kOperandKind, int kNumCachedOperands> | 62 template <InstructionOperand::Kind kOperandKind, int kNumCachedOperands> |
67 SubKindOperand<kOperandKind, kNumCachedOperands>* | 63 SubKindOperand<kOperandKind, kNumCachedOperands>* |
68 SubKindOperand<kOperandKind, kNumCachedOperands>::cache = NULL; | 64 SubKindOperand<kOperandKind, kNumCachedOperands>::cache = NULL; |
69 | 65 |
(...skipping 24 matching lines...) Expand all Loading... |
94 | 90 |
95 | 91 |
96 void InstructionOperand::TearDownCaches() { | 92 void InstructionOperand::TearDownCaches() { |
97 #define INSTRUCTION_OPERAND_TEARDOWN(name, type, number) \ | 93 #define INSTRUCTION_OPERAND_TEARDOWN(name, type, number) \ |
98 name##Operand::TearDownCache(); | 94 name##Operand::TearDownCache(); |
99 INSTRUCTION_OPERAND_LIST(INSTRUCTION_OPERAND_TEARDOWN) | 95 INSTRUCTION_OPERAND_LIST(INSTRUCTION_OPERAND_TEARDOWN) |
100 #undef INSTRUCTION_OPERAND_TEARDOWN | 96 #undef INSTRUCTION_OPERAND_TEARDOWN |
101 } | 97 } |
102 | 98 |
103 | 99 |
104 std::ostream& operator<<(std::ostream& os, const MoveOperands& mo) { | 100 std::ostream& operator<<(std::ostream& os, |
105 os << *mo.destination(); | 101 const PrintableMoveOperands& printable) { |
106 if (!mo.source()->Equals(mo.destination())) os << " = " << *mo.source(); | 102 const MoveOperands& mo = *printable.move_operands_; |
| 103 PrintableInstructionOperand printable_op = {printable.register_configuration_, |
| 104 mo.destination()}; |
| 105 |
| 106 os << printable_op; |
| 107 if (!mo.source()->Equals(mo.destination())) { |
| 108 printable_op.op_ = mo.source(); |
| 109 os << " = " << printable_op; |
| 110 } |
107 return os << ";"; | 111 return os << ";"; |
108 } | 112 } |
109 | 113 |
110 | 114 |
111 bool ParallelMove::IsRedundant() const { | 115 bool ParallelMove::IsRedundant() const { |
112 for (int i = 0; i < move_operands_.length(); ++i) { | 116 for (int i = 0; i < move_operands_.length(); ++i) { |
113 if (!move_operands_[i].IsRedundant()) return false; | 117 if (!move_operands_[i].IsRedundant()) return false; |
114 } | 118 } |
115 return true; | 119 return true; |
116 } | 120 } |
117 | 121 |
118 | 122 |
119 std::ostream& operator<<(std::ostream& os, const ParallelMove& pm) { | 123 std::ostream& operator<<(std::ostream& os, |
| 124 const PrintableParallelMove& printable) { |
| 125 const ParallelMove& pm = *printable.parallel_move_; |
120 bool first = true; | 126 bool first = true; |
121 for (ZoneList<MoveOperands>::iterator move = pm.move_operands()->begin(); | 127 for (ZoneList<MoveOperands>::iterator move = pm.move_operands()->begin(); |
122 move != pm.move_operands()->end(); ++move) { | 128 move != pm.move_operands()->end(); ++move) { |
123 if (move->IsEliminated()) continue; | 129 if (move->IsEliminated()) continue; |
124 if (!first) os << " "; | 130 if (!first) os << " "; |
125 first = false; | 131 first = false; |
126 os << *move; | 132 PrintableMoveOperands pmo = {printable.register_configuration_, move}; |
| 133 os << pmo; |
127 } | 134 } |
128 return os; | 135 return os; |
129 } | 136 } |
130 | 137 |
131 | 138 |
132 void PointerMap::RecordPointer(InstructionOperand* op, Zone* zone) { | 139 void PointerMap::RecordPointer(InstructionOperand* op, Zone* zone) { |
133 // Do not record arguments as pointers. | 140 // Do not record arguments as pointers. |
134 if (op->IsStackSlot() && op->index() < 0) return; | 141 if (op->IsStackSlot() && op->index() < 0) return; |
135 DCHECK(!op->IsDoubleRegister() && !op->IsDoubleStackSlot()); | 142 DCHECK(!op->IsDoubleRegister() && !op->IsDoubleStackSlot()); |
136 pointer_operands_.Add(op, zone); | 143 pointer_operands_.Add(op, zone); |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
249 case kOverflow: | 256 case kOverflow: |
250 return os << "overflow"; | 257 return os << "overflow"; |
251 case kNotOverflow: | 258 case kNotOverflow: |
252 return os << "not overflow"; | 259 return os << "not overflow"; |
253 } | 260 } |
254 UNREACHABLE(); | 261 UNREACHABLE(); |
255 return os; | 262 return os; |
256 } | 263 } |
257 | 264 |
258 | 265 |
259 std::ostream& operator<<(std::ostream& os, const Instruction& instr) { | 266 std::ostream& operator<<(std::ostream& os, |
| 267 const PrintableInstruction& printable) { |
| 268 const Instruction& instr = *printable.instr_; |
| 269 PrintableInstructionOperand printable_op = {printable.register_configuration_, |
| 270 NULL}; |
260 if (instr.OutputCount() > 1) os << "("; | 271 if (instr.OutputCount() > 1) os << "("; |
261 for (size_t i = 0; i < instr.OutputCount(); i++) { | 272 for (size_t i = 0; i < instr.OutputCount(); i++) { |
262 if (i > 0) os << ", "; | 273 if (i > 0) os << ", "; |
263 os << *instr.OutputAt(i); | 274 printable_op.op_ = instr.OutputAt(i); |
| 275 os << printable_op; |
264 } | 276 } |
265 | 277 |
266 if (instr.OutputCount() > 1) os << ") = "; | 278 if (instr.OutputCount() > 1) os << ") = "; |
267 if (instr.OutputCount() == 1) os << " = "; | 279 if (instr.OutputCount() == 1) os << " = "; |
268 | 280 |
269 if (instr.IsGapMoves()) { | 281 if (instr.IsGapMoves()) { |
270 const GapInstruction* gap = GapInstruction::cast(&instr); | 282 const GapInstruction* gap = GapInstruction::cast(&instr); |
271 os << (instr.IsBlockStart() ? " block-start" : "gap "); | 283 os << (instr.IsBlockStart() ? " block-start" : "gap "); |
272 for (int i = GapInstruction::FIRST_INNER_POSITION; | 284 for (int i = GapInstruction::FIRST_INNER_POSITION; |
273 i <= GapInstruction::LAST_INNER_POSITION; i++) { | 285 i <= GapInstruction::LAST_INNER_POSITION; i++) { |
274 os << "("; | 286 os << "("; |
275 if (gap->parallel_moves_[i] != NULL) os << *gap->parallel_moves_[i]; | 287 if (gap->parallel_moves_[i] != NULL) { |
| 288 PrintableParallelMove ppm = {printable.register_configuration_, |
| 289 gap->parallel_moves_[i]}; |
| 290 os << ppm; |
| 291 } |
276 os << ") "; | 292 os << ") "; |
277 } | 293 } |
278 } else if (instr.IsSourcePosition()) { | 294 } else if (instr.IsSourcePosition()) { |
279 const SourcePositionInstruction* pos = | 295 const SourcePositionInstruction* pos = |
280 SourcePositionInstruction::cast(&instr); | 296 SourcePositionInstruction::cast(&instr); |
281 os << "position (" << pos->source_position().raw() << ")"; | 297 os << "position (" << pos->source_position().raw() << ")"; |
282 } else { | 298 } else { |
283 os << ArchOpcodeField::decode(instr.opcode()); | 299 os << ArchOpcodeField::decode(instr.opcode()); |
284 AddressingMode am = AddressingModeField::decode(instr.opcode()); | 300 AddressingMode am = AddressingModeField::decode(instr.opcode()); |
285 if (am != kMode_None) { | 301 if (am != kMode_None) { |
286 os << " : " << AddressingModeField::decode(instr.opcode()); | 302 os << " : " << AddressingModeField::decode(instr.opcode()); |
287 } | 303 } |
288 FlagsMode fm = FlagsModeField::decode(instr.opcode()); | 304 FlagsMode fm = FlagsModeField::decode(instr.opcode()); |
289 if (fm != kFlags_none) { | 305 if (fm != kFlags_none) { |
290 os << " && " << fm << " if " | 306 os << " && " << fm << " if " |
291 << FlagsConditionField::decode(instr.opcode()); | 307 << FlagsConditionField::decode(instr.opcode()); |
292 } | 308 } |
293 } | 309 } |
294 if (instr.InputCount() > 0) { | 310 if (instr.InputCount() > 0) { |
295 for (size_t i = 0; i < instr.InputCount(); i++) { | 311 for (size_t i = 0; i < instr.InputCount(); i++) { |
296 os << " " << *instr.InputAt(i); | 312 printable_op.op_ = instr.InputAt(i); |
| 313 os << " " << printable_op; |
297 } | 314 } |
298 } | 315 } |
299 return os; | 316 return os; |
300 } | 317 } |
301 | 318 |
302 | 319 |
303 std::ostream& operator<<(std::ostream& os, const Constant& constant) { | 320 std::ostream& operator<<(std::ostream& os, const Constant& constant) { |
304 switch (constant.type()) { | 321 switch (constant.type()) { |
305 case Constant::kInt32: | 322 case Constant::kInt32: |
306 return os << constant.ToInt32(); | 323 return os << constant.ToInt32(); |
(...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
578 return types_[index]; | 595 return types_[index]; |
579 } | 596 } |
580 | 597 |
581 | 598 |
582 void FrameStateDescriptor::SetType(size_t index, MachineType type) { | 599 void FrameStateDescriptor::SetType(size_t index, MachineType type) { |
583 DCHECK(index < GetSize()); | 600 DCHECK(index < GetSize()); |
584 types_[index] = type; | 601 types_[index] = type; |
585 } | 602 } |
586 | 603 |
587 | 604 |
588 std::ostream& operator<<(std::ostream& os, const InstructionSequence& code) { | 605 std::ostream& operator<<(std::ostream& os, |
| 606 const PrintableInstructionSequence& printable) { |
| 607 const InstructionSequence& code = *printable.sequence_; |
589 for (size_t i = 0; i < code.immediates_.size(); ++i) { | 608 for (size_t i = 0; i < code.immediates_.size(); ++i) { |
590 Constant constant = code.immediates_[i]; | 609 Constant constant = code.immediates_[i]; |
591 os << "IMM#" << i << ": " << constant << "\n"; | 610 os << "IMM#" << i << ": " << constant << "\n"; |
592 } | 611 } |
593 int i = 0; | 612 int i = 0; |
594 for (ConstantMap::const_iterator it = code.constants_.begin(); | 613 for (ConstantMap::const_iterator it = code.constants_.begin(); |
595 it != code.constants_.end(); ++i, ++it) { | 614 it != code.constants_.end(); ++i, ++it) { |
596 os << "CST#" << i << ": v" << it->first << " = " << it->second << "\n"; | 615 os << "CST#" << i << ": v" << it->first << " = " << it->second << "\n"; |
597 } | 616 } |
598 for (int i = 0; i < code.InstructionBlockCount(); i++) { | 617 for (int i = 0; i < code.InstructionBlockCount(); i++) { |
(...skipping 20 matching lines...) Expand all Loading... |
619 | 638 |
620 for (auto phi : block->phis()) { | 639 for (auto phi : block->phis()) { |
621 os << " phi: v" << phi->virtual_register() << " ="; | 640 os << " phi: v" << phi->virtual_register() << " ="; |
622 for (auto op_vreg : phi->operands()) { | 641 for (auto op_vreg : phi->operands()) { |
623 os << " v" << op_vreg; | 642 os << " v" << op_vreg; |
624 } | 643 } |
625 os << "\n"; | 644 os << "\n"; |
626 } | 645 } |
627 | 646 |
628 ScopedVector<char> buf(32); | 647 ScopedVector<char> buf(32); |
| 648 PrintableInstruction printable_instr; |
| 649 printable_instr.register_configuration_ = printable.register_configuration_; |
629 for (int j = block->first_instruction_index(); | 650 for (int j = block->first_instruction_index(); |
630 j <= block->last_instruction_index(); j++) { | 651 j <= block->last_instruction_index(); j++) { |
631 // TODO(svenpanne) Add some basic formatting to our streams. | 652 // TODO(svenpanne) Add some basic formatting to our streams. |
632 SNPrintF(buf, "%5d", j); | 653 SNPrintF(buf, "%5d", j); |
633 os << " " << buf.start() << ": " << *code.InstructionAt(j) << "\n"; | 654 printable_instr.instr_ = code.InstructionAt(j); |
| 655 os << " " << buf.start() << ": " << printable_instr << "\n"; |
634 } | 656 } |
635 | 657 |
636 // TODO(dcarney): add this back somehow? | |
637 // os << " " << block->control(); | |
638 | |
639 // if (block->control_input() != NULL) { | |
640 // os << " v" << block->control_input()->id(); | |
641 // } | |
642 | |
643 for (auto succ : block->successors()) { | 658 for (auto succ : block->successors()) { |
644 const InstructionBlock* succ_block = code.InstructionBlockAt(succ); | 659 const InstructionBlock* succ_block = code.InstructionBlockAt(succ); |
645 os << " B" << succ_block->id(); | 660 os << " B" << succ_block->id(); |
646 } | 661 } |
647 os << "\n"; | 662 os << "\n"; |
648 } | 663 } |
649 return os; | 664 return os; |
650 } | 665 } |
651 | 666 |
652 } // namespace compiler | 667 } // namespace compiler |
653 } // namespace internal | 668 } // namespace internal |
654 } // namespace v8 | 669 } // namespace v8 |
OLD | NEW |