| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 19 matching lines...) Expand all Loading... |
| 30 #if defined(V8_TARGET_ARCH_X64) | 30 #if defined(V8_TARGET_ARCH_X64) |
| 31 | 31 |
| 32 #include "x64/lithium-codegen-x64.h" | 32 #include "x64/lithium-codegen-x64.h" |
| 33 #include "code-stubs.h" | 33 #include "code-stubs.h" |
| 34 #include "stub-cache.h" | 34 #include "stub-cache.h" |
| 35 | 35 |
| 36 namespace v8 { | 36 namespace v8 { |
| 37 namespace internal { | 37 namespace internal { |
| 38 | 38 |
| 39 | 39 |
| 40 class LGapNode: public ZoneObject { | |
| 41 public: | |
| 42 explicit LGapNode(LOperand* operand) | |
| 43 : operand_(operand), resolved_(false), visited_id_(-1) { } | |
| 44 | |
| 45 LOperand* operand() const { return operand_; } | |
| 46 bool IsResolved() const { return !IsAssigned() || resolved_; } | |
| 47 void MarkResolved() { | |
| 48 ASSERT(!IsResolved()); | |
| 49 resolved_ = true; | |
| 50 } | |
| 51 int visited_id() const { return visited_id_; } | |
| 52 void set_visited_id(int id) { | |
| 53 ASSERT(id > visited_id_); | |
| 54 visited_id_ = id; | |
| 55 } | |
| 56 | |
| 57 bool IsAssigned() const { return assigned_from_.is_set(); } | |
| 58 LGapNode* assigned_from() const { return assigned_from_.get(); } | |
| 59 void set_assigned_from(LGapNode* n) { assigned_from_.set(n); } | |
| 60 | |
| 61 private: | |
| 62 LOperand* operand_; | |
| 63 SetOncePointer<LGapNode> assigned_from_; | |
| 64 bool resolved_; | |
| 65 int visited_id_; | |
| 66 }; | |
| 67 | |
| 68 | |
| 69 LGapResolver::LGapResolver() | |
| 70 : nodes_(32), | |
| 71 identified_cycles_(4), | |
| 72 result_(16), | |
| 73 next_visited_id_(0) { | |
| 74 } | |
| 75 | |
| 76 | |
| 77 const ZoneList<LMoveOperands>* LGapResolver::Resolve( | |
| 78 const ZoneList<LMoveOperands>* moves, | |
| 79 LOperand* marker_operand) { | |
| 80 nodes_.Rewind(0); | |
| 81 identified_cycles_.Rewind(0); | |
| 82 result_.Rewind(0); | |
| 83 next_visited_id_ = 0; | |
| 84 | |
| 85 for (int i = 0; i < moves->length(); ++i) { | |
| 86 LMoveOperands move = moves->at(i); | |
| 87 if (!move.IsRedundant()) RegisterMove(move); | |
| 88 } | |
| 89 | |
| 90 for (int i = 0; i < identified_cycles_.length(); ++i) { | |
| 91 ResolveCycle(identified_cycles_[i], marker_operand); | |
| 92 } | |
| 93 | |
| 94 int unresolved_nodes; | |
| 95 do { | |
| 96 unresolved_nodes = 0; | |
| 97 for (int j = 0; j < nodes_.length(); j++) { | |
| 98 LGapNode* node = nodes_[j]; | |
| 99 if (!node->IsResolved() && node->assigned_from()->IsResolved()) { | |
| 100 AddResultMove(node->assigned_from(), node); | |
| 101 node->MarkResolved(); | |
| 102 } | |
| 103 if (!node->IsResolved()) ++unresolved_nodes; | |
| 104 } | |
| 105 } while (unresolved_nodes > 0); | |
| 106 return &result_; | |
| 107 } | |
| 108 | |
| 109 | |
| 110 void LGapResolver::AddResultMove(LGapNode* from, LGapNode* to) { | |
| 111 AddResultMove(from->operand(), to->operand()); | |
| 112 } | |
| 113 | |
| 114 | |
| 115 void LGapResolver::AddResultMove(LOperand* from, LOperand* to) { | |
| 116 result_.Add(LMoveOperands(from, to)); | |
| 117 } | |
| 118 | |
| 119 | |
| 120 void LGapResolver::ResolveCycle(LGapNode* start, LOperand* marker_operand) { | |
| 121 ZoneList<LOperand*> cycle_operands(8); | |
| 122 cycle_operands.Add(marker_operand); | |
| 123 LGapNode* cur = start; | |
| 124 do { | |
| 125 cur->MarkResolved(); | |
| 126 cycle_operands.Add(cur->operand()); | |
| 127 cur = cur->assigned_from(); | |
| 128 } while (cur != start); | |
| 129 cycle_operands.Add(marker_operand); | |
| 130 | |
| 131 for (int i = cycle_operands.length() - 1; i > 0; --i) { | |
| 132 LOperand* from = cycle_operands[i]; | |
| 133 LOperand* to = cycle_operands[i - 1]; | |
| 134 AddResultMove(from, to); | |
| 135 } | |
| 136 } | |
| 137 | |
| 138 | |
| 139 bool LGapResolver::CanReach(LGapNode* a, LGapNode* b, int visited_id) { | |
| 140 ASSERT(a != b); | |
| 141 LGapNode* cur = a; | |
| 142 while (cur != b && cur->visited_id() != visited_id && cur->IsAssigned()) { | |
| 143 cur->set_visited_id(visited_id); | |
| 144 cur = cur->assigned_from(); | |
| 145 } | |
| 146 | |
| 147 return cur == b; | |
| 148 } | |
| 149 | |
| 150 | |
| 151 bool LGapResolver::CanReach(LGapNode* a, LGapNode* b) { | |
| 152 ASSERT(a != b); | |
| 153 return CanReach(a, b, next_visited_id_++); | |
| 154 } | |
| 155 | |
| 156 | |
| 157 void LGapResolver::RegisterMove(LMoveOperands move) { | |
| 158 if (move.source()->IsConstantOperand()) { | |
| 159 // Constant moves should be last in the machine code. Therefore add them | |
| 160 // first to the result set. | |
| 161 AddResultMove(move.source(), move.destination()); | |
| 162 } else { | |
| 163 LGapNode* from = LookupNode(move.source()); | |
| 164 LGapNode* to = LookupNode(move.destination()); | |
| 165 if (to->IsAssigned() && to->assigned_from() == from) { | |
| 166 move.Eliminate(); | |
| 167 return; | |
| 168 } | |
| 169 ASSERT(!to->IsAssigned()); | |
| 170 if (CanReach(from, to)) { | |
| 171 // This introduces a cycle. Save. | |
| 172 identified_cycles_.Add(from); | |
| 173 } | |
| 174 to->set_assigned_from(from); | |
| 175 } | |
| 176 } | |
| 177 | |
| 178 | |
| 179 LGapNode* LGapResolver::LookupNode(LOperand* operand) { | |
| 180 for (int i = 0; i < nodes_.length(); ++i) { | |
| 181 if (nodes_[i]->operand()->Equals(operand)) return nodes_[i]; | |
| 182 } | |
| 183 | |
| 184 // No node found => create a new one. | |
| 185 LGapNode* result = new LGapNode(operand); | |
| 186 nodes_.Add(result); | |
| 187 return result; | |
| 188 } | |
| 189 | |
| 190 | |
| 191 #define __ masm()-> | 40 #define __ masm()-> |
| 192 | 41 |
| 193 bool LCodeGen::GenerateCode() { | 42 bool LCodeGen::GenerateCode() { |
| 194 HPhase phase("Code generation", chunk()); | 43 HPhase phase("Code generation", chunk()); |
| 195 ASSERT(is_unused()); | 44 ASSERT(is_unused()); |
| 196 status_ = GENERATING; | 45 status_ = GENERATING; |
| 197 return GeneratePrologue() && | 46 return GeneratePrologue() && |
| 198 GenerateBody() && | 47 GenerateBody() && |
| 199 GenerateDeferredCode() && | 48 GenerateDeferredCode() && |
| 200 GenerateSafepointTable(); | 49 GenerateSafepointTable(); |
| (...skipping 474 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 675 } else { | 524 } else { |
| 676 Comment(";;; B%d", label->block_id()); | 525 Comment(";;; B%d", label->block_id()); |
| 677 } | 526 } |
| 678 __ bind(label->label()); | 527 __ bind(label->label()); |
| 679 current_block_ = label->block_id(); | 528 current_block_ = label->block_id(); |
| 680 LCodeGen::DoGap(label); | 529 LCodeGen::DoGap(label); |
| 681 } | 530 } |
| 682 | 531 |
| 683 | 532 |
| 684 void LCodeGen::DoParallelMove(LParallelMove* move) { | 533 void LCodeGen::DoParallelMove(LParallelMove* move) { |
| 685 // xmm0 must always be a scratch register. | 534 resolver_.Resolve(move); |
| 686 XMMRegister xmm_scratch = xmm0; | |
| 687 LUnallocated marker_operand(LUnallocated::NONE); | |
| 688 | |
| 689 Register cpu_scratch = kScratchRegister; | |
| 690 | |
| 691 const ZoneList<LMoveOperands>* moves = | |
| 692 resolver_.Resolve(move->move_operands(), &marker_operand); | |
| 693 for (int i = moves->length() - 1; i >= 0; --i) { | |
| 694 LMoveOperands move = moves->at(i); | |
| 695 LOperand* from = move.source(); | |
| 696 LOperand* to = move.destination(); | |
| 697 ASSERT(!from->IsDoubleRegister() || | |
| 698 !ToDoubleRegister(from).is(xmm_scratch)); | |
| 699 ASSERT(!to->IsDoubleRegister() || !ToDoubleRegister(to).is(xmm_scratch)); | |
| 700 ASSERT(!from->IsRegister() || !ToRegister(from).is(cpu_scratch)); | |
| 701 ASSERT(!to->IsRegister() || !ToRegister(to).is(cpu_scratch)); | |
| 702 if (from->IsConstantOperand()) { | |
| 703 LConstantOperand* constant_from = LConstantOperand::cast(from); | |
| 704 if (to->IsRegister()) { | |
| 705 if (IsInteger32Constant(constant_from)) { | |
| 706 __ movl(ToRegister(to), Immediate(ToInteger32(constant_from))); | |
| 707 } else { | |
| 708 __ Move(ToRegister(to), ToHandle(constant_from)); | |
| 709 } | |
| 710 } else { | |
| 711 if (IsInteger32Constant(constant_from)) { | |
| 712 __ movl(ToOperand(to), Immediate(ToInteger32(constant_from))); | |
| 713 } else { | |
| 714 __ Move(ToOperand(to), ToHandle(constant_from)); | |
| 715 } | |
| 716 } | |
| 717 } else if (from == &marker_operand) { | |
| 718 if (to->IsRegister()) { | |
| 719 __ movq(ToRegister(to), cpu_scratch); | |
| 720 } else if (to->IsStackSlot()) { | |
| 721 __ movq(ToOperand(to), cpu_scratch); | |
| 722 } else if (to->IsDoubleRegister()) { | |
| 723 __ movsd(ToDoubleRegister(to), xmm_scratch); | |
| 724 } else { | |
| 725 ASSERT(to->IsDoubleStackSlot()); | |
| 726 __ movsd(ToOperand(to), xmm_scratch); | |
| 727 } | |
| 728 } else if (to == &marker_operand) { | |
| 729 if (from->IsRegister()) { | |
| 730 __ movq(cpu_scratch, ToRegister(from)); | |
| 731 } else if (from->IsStackSlot()) { | |
| 732 __ movq(cpu_scratch, ToOperand(from)); | |
| 733 } else if (from->IsDoubleRegister()) { | |
| 734 __ movsd(xmm_scratch, ToDoubleRegister(from)); | |
| 735 } else { | |
| 736 ASSERT(from->IsDoubleStackSlot()); | |
| 737 __ movsd(xmm_scratch, ToOperand(from)); | |
| 738 } | |
| 739 } else if (from->IsRegister()) { | |
| 740 if (to->IsRegister()) { | |
| 741 __ movq(ToRegister(to), ToRegister(from)); | |
| 742 } else { | |
| 743 __ movq(ToOperand(to), ToRegister(from)); | |
| 744 } | |
| 745 } else if (to->IsRegister()) { | |
| 746 __ movq(ToRegister(to), ToOperand(from)); | |
| 747 } else if (from->IsStackSlot()) { | |
| 748 ASSERT(to->IsStackSlot()); | |
| 749 __ push(rax); | |
| 750 __ movq(rax, ToOperand(from)); | |
| 751 __ movq(ToOperand(to), rax); | |
| 752 __ pop(rax); | |
| 753 } else if (from->IsDoubleRegister()) { | |
| 754 ASSERT(to->IsDoubleStackSlot()); | |
| 755 __ movsd(ToOperand(to), ToDoubleRegister(from)); | |
| 756 } else if (to->IsDoubleRegister()) { | |
| 757 ASSERT(from->IsDoubleStackSlot()); | |
| 758 __ movsd(ToDoubleRegister(to), ToOperand(from)); | |
| 759 } else { | |
| 760 ASSERT(to->IsDoubleStackSlot() && from->IsDoubleStackSlot()); | |
| 761 __ movsd(xmm_scratch, ToOperand(from)); | |
| 762 __ movsd(ToOperand(to), xmm_scratch); | |
| 763 } | |
| 764 } | |
| 765 } | 535 } |
| 766 | 536 |
| 767 | 537 |
| 768 void LCodeGen::DoGap(LGap* gap) { | 538 void LCodeGen::DoGap(LGap* gap) { |
| 769 for (int i = LGap::FIRST_INNER_POSITION; | 539 for (int i = LGap::FIRST_INNER_POSITION; |
| 770 i <= LGap::LAST_INNER_POSITION; | 540 i <= LGap::LAST_INNER_POSITION; |
| 771 i++) { | 541 i++) { |
| 772 LGap::InnerPosition inner_pos = static_cast<LGap::InnerPosition>(i); | 542 LGap::InnerPosition inner_pos = static_cast<LGap::InnerPosition>(i); |
| 773 LParallelMove* move = gap->GetParallelMove(inner_pos); | 543 LParallelMove* move = gap->GetParallelMove(inner_pos); |
| 774 if (move != NULL) DoParallelMove(move); | 544 if (move != NULL) DoParallelMove(move); |
| (...skipping 1157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1932 | 1702 |
| 1933 void LCodeGen::DoOsrEntry(LOsrEntry* instr) { | 1703 void LCodeGen::DoOsrEntry(LOsrEntry* instr) { |
| 1934 Abort("Unimplemented: %s", "DoOsrEntry"); | 1704 Abort("Unimplemented: %s", "DoOsrEntry"); |
| 1935 } | 1705 } |
| 1936 | 1706 |
| 1937 #undef __ | 1707 #undef __ |
| 1938 | 1708 |
| 1939 } } // namespace v8::internal | 1709 } } // namespace v8::internal |
| 1940 | 1710 |
| 1941 #endif // V8_TARGET_ARCH_X64 | 1711 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |