Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(605)

Side by Side Diff: src/ia32/lithium-codegen-ia32.cc

Issue 6263005: Change the algorithm and generated code for parallel moves on IA32. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge/build/ia32
Patch Set: Fix compilation on all platforms. Created 9 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
51 codegen_->RecordSafepoint(pointers_, deoptimization_index_); 51 codegen_->RecordSafepoint(pointers_, deoptimization_index_);
52 } 52 }
53 53
54 private: 54 private:
55 LCodeGen* codegen_; 55 LCodeGen* codegen_;
56 LPointerMap* pointers_; 56 LPointerMap* pointers_;
57 int deoptimization_index_; 57 int deoptimization_index_;
58 }; 58 };
59 59
60 60
61 class LGapNode: public ZoneObject {
62 public:
63 explicit LGapNode(LOperand* operand)
64 : operand_(operand), resolved_(false), visited_id_(-1) { }
65
66 LOperand* operand() const { return operand_; }
67 bool IsResolved() const { return !IsAssigned() || resolved_; }
68 void MarkResolved() {
69 ASSERT(!IsResolved());
70 resolved_ = true;
71 }
72 int visited_id() const { return visited_id_; }
73 void set_visited_id(int id) {
74 ASSERT(id > visited_id_);
75 visited_id_ = id;
76 }
77
78 bool IsAssigned() const { return assigned_from_.is_set(); }
79 LGapNode* assigned_from() const { return assigned_from_.get(); }
80 void set_assigned_from(LGapNode* n) { assigned_from_.set(n); }
81
82 private:
83 LOperand* operand_;
84 SetOncePointer<LGapNode> assigned_from_;
85 bool resolved_;
86 int visited_id_;
87 };
88
89
90 LGapResolver::LGapResolver()
91 : nodes_(32),
92 identified_cycles_(4),
93 result_(16),
94 next_visited_id_(0) {
95 }
96
97
98 const ZoneList<LMoveOperands>* LGapResolver::Resolve(
99 const ZoneList<LMoveOperands>* moves,
100 LOperand* marker_operand) {
101 nodes_.Rewind(0);
102 identified_cycles_.Rewind(0);
103 result_.Rewind(0);
104 next_visited_id_ = 0;
105
106 for (int i = 0; i < moves->length(); ++i) {
107 LMoveOperands move = moves->at(i);
108 if (!move.IsRedundant()) RegisterMove(move);
109 }
110
111 for (int i = 0; i < identified_cycles_.length(); ++i) {
112 ResolveCycle(identified_cycles_[i], marker_operand);
113 }
114
115 int unresolved_nodes;
116 do {
117 unresolved_nodes = 0;
118 for (int j = 0; j < nodes_.length(); j++) {
119 LGapNode* node = nodes_[j];
120 if (!node->IsResolved() && node->assigned_from()->IsResolved()) {
121 AddResultMove(node->assigned_from(), node);
122 node->MarkResolved();
123 }
124 if (!node->IsResolved()) ++unresolved_nodes;
125 }
126 } while (unresolved_nodes > 0);
127 return &result_;
128 }
129
130
131 void LGapResolver::AddResultMove(LGapNode* from, LGapNode* to) {
132 AddResultMove(from->operand(), to->operand());
133 }
134
135
136 void LGapResolver::AddResultMove(LOperand* from, LOperand* to) {
137 result_.Add(LMoveOperands(from, to));
138 }
139
140
141 void LGapResolver::ResolveCycle(LGapNode* start, LOperand* marker_operand) {
142 ZoneList<LOperand*> cycle_operands(8);
143 cycle_operands.Add(marker_operand);
144 LGapNode* cur = start;
145 do {
146 cur->MarkResolved();
147 cycle_operands.Add(cur->operand());
148 cur = cur->assigned_from();
149 } while (cur != start);
150 cycle_operands.Add(marker_operand);
151
152 for (int i = cycle_operands.length() - 1; i > 0; --i) {
153 LOperand* from = cycle_operands[i];
154 LOperand* to = cycle_operands[i - 1];
155 AddResultMove(from, to);
156 }
157 }
158
159
160 bool LGapResolver::CanReach(LGapNode* a, LGapNode* b, int visited_id) {
161 ASSERT(a != b);
162 LGapNode* cur = a;
163 while (cur != b && cur->visited_id() != visited_id && cur->IsAssigned()) {
164 cur->set_visited_id(visited_id);
165 cur = cur->assigned_from();
166 }
167
168 return cur == b;
169 }
170
171
172 bool LGapResolver::CanReach(LGapNode* a, LGapNode* b) {
173 ASSERT(a != b);
174 return CanReach(a, b, next_visited_id_++);
175 }
176
177
178 void LGapResolver::RegisterMove(LMoveOperands move) {
179 if (move.from()->IsConstantOperand()) {
180 // Constant moves should be last in the machine code. Therefore add them
181 // first to the result set.
182 AddResultMove(move.from(), move.to());
183 } else {
184 LGapNode* from = LookupNode(move.from());
185 LGapNode* to = LookupNode(move.to());
186 if (to->IsAssigned() && to->assigned_from() == from) {
187 move.Eliminate();
188 return;
189 }
190 ASSERT(!to->IsAssigned());
191 if (CanReach(from, to)) {
192 // This introduces a cycle. Save.
193 identified_cycles_.Add(from);
194 }
195 to->set_assigned_from(from);
196 }
197 }
198
199
200 LGapNode* LGapResolver::LookupNode(LOperand* operand) {
201 for (int i = 0; i < nodes_.length(); ++i) {
202 if (nodes_[i]->operand()->Equals(operand)) return nodes_[i];
203 }
204
205 // No node found => create a new one.
206 LGapNode* result = new LGapNode(operand);
207 nodes_.Add(result);
208 return result;
209 }
210
211
212 #define __ masm()-> 61 #define __ masm()->
213 62
214 bool LCodeGen::GenerateCode() { 63 bool LCodeGen::GenerateCode() {
215 HPhase phase("Code generation", chunk()); 64 HPhase phase("Code generation", chunk());
216 ASSERT(is_unused()); 65 ASSERT(is_unused());
217 status_ = GENERATING; 66 status_ = GENERATING;
218 CpuFeatures::Scope scope(SSE2); 67 CpuFeatures::Scope scope(SSE2);
219 return GeneratePrologue() && 68 return GeneratePrologue() &&
220 GenerateBody() && 69 GenerateBody() &&
221 GenerateDeferredCode() && 70 GenerateDeferredCode() &&
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after
420 // Local or spill slot. Skip the frame pointer, function, and 269 // Local or spill slot. Skip the frame pointer, function, and
421 // context in the fixed part of the frame. 270 // context in the fixed part of the frame.
422 return Operand(ebp, -(index + 3) * kPointerSize); 271 return Operand(ebp, -(index + 3) * kPointerSize);
423 } else { 272 } else {
424 // Incoming parameter. Skip the return address. 273 // Incoming parameter. Skip the return address.
425 return Operand(ebp, -(index - 1) * kPointerSize); 274 return Operand(ebp, -(index - 1) * kPointerSize);
426 } 275 }
427 } 276 }
428 277
429 278
279 Operand LCodeGen::HighOperand(LOperand* op) {
280 ASSERT(op->IsDoubleStackSlot());
281 int index = op->index();
282 int offset = (index >= 0) ? index + 3 : index - 1;
283 return Operand(ebp, -offset * kPointerSize);
284 }
285
286
430 void LCodeGen::WriteTranslation(LEnvironment* environment, 287 void LCodeGen::WriteTranslation(LEnvironment* environment,
431 Translation* translation) { 288 Translation* translation) {
432 if (environment == NULL) return; 289 if (environment == NULL) return;
433 290
434 // The translation includes one command per value in the environment. 291 // The translation includes one command per value in the environment.
435 int translation_size = environment->values()->length(); 292 int translation_size = environment->values()->length();
436 // The output frame height does not include the parameters. 293 // The output frame height does not include the parameters.
437 int height = translation_size - environment->parameter_count(); 294 int height = translation_size - environment->parameter_count();
438 295
439 WriteTranslation(environment->outer(), translation); 296 WriteTranslation(environment->outer(), translation);
(...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after
755 } else { 612 } else {
756 Comment(";;; B%d", label->block_id()); 613 Comment(";;; B%d", label->block_id());
757 } 614 }
758 __ bind(label->label()); 615 __ bind(label->label());
759 current_block_ = label->block_id(); 616 current_block_ = label->block_id();
760 LCodeGen::DoGap(label); 617 LCodeGen::DoGap(label);
761 } 618 }
762 619
763 620
764 void LCodeGen::DoParallelMove(LParallelMove* move) { 621 void LCodeGen::DoParallelMove(LParallelMove* move) {
765 // xmm0 must always be a scratch register. 622 resolver_.Resolve(move);
766 XMMRegister xmm_scratch = xmm0;
767 LUnallocated marker_operand(LUnallocated::NONE);
768
769 Register cpu_scratch = esi;
770 bool destroys_cpu_scratch = false;
771
772 const ZoneList<LMoveOperands>* moves =
773 resolver_.Resolve(move->move_operands(), &marker_operand);
774 for (int i = moves->length() - 1; i >= 0; --i) {
775 LMoveOperands move = moves->at(i);
776 LOperand* from = move.from();
777 LOperand* to = move.to();
778 ASSERT(!from->IsDoubleRegister() ||
779 !ToDoubleRegister(from).is(xmm_scratch));
780 ASSERT(!to->IsDoubleRegister() || !ToDoubleRegister(to).is(xmm_scratch));
781 ASSERT(!from->IsRegister() || !ToRegister(from).is(cpu_scratch));
782 ASSERT(!to->IsRegister() || !ToRegister(to).is(cpu_scratch));
783 if (from->IsConstantOperand()) {
784 __ mov(ToOperand(to), ToImmediate(from));
785 } else if (from == &marker_operand) {
786 if (to->IsRegister() || to->IsStackSlot()) {
787 __ mov(ToOperand(to), cpu_scratch);
788 ASSERT(destroys_cpu_scratch);
789 } else {
790 ASSERT(to->IsDoubleRegister() || to->IsDoubleStackSlot());
791 __ movdbl(ToOperand(to), xmm_scratch);
792 }
793 } else if (to == &marker_operand) {
794 if (from->IsRegister() || from->IsStackSlot()) {
795 __ mov(cpu_scratch, ToOperand(from));
796 destroys_cpu_scratch = true;
797 } else {
798 ASSERT(from->IsDoubleRegister() || from->IsDoubleStackSlot());
799 __ movdbl(xmm_scratch, ToOperand(from));
800 }
801 } else if (from->IsRegister()) {
802 __ mov(ToOperand(to), ToRegister(from));
803 } else if (to->IsRegister()) {
804 __ mov(ToRegister(to), ToOperand(from));
805 } else if (from->IsStackSlot()) {
806 ASSERT(to->IsStackSlot());
807 __ push(eax);
808 __ mov(eax, ToOperand(from));
809 __ mov(ToOperand(to), eax);
810 __ pop(eax);
811 } else if (from->IsDoubleRegister()) {
812 __ movdbl(ToOperand(to), ToDoubleRegister(from));
813 } else if (to->IsDoubleRegister()) {
814 __ movdbl(ToDoubleRegister(to), ToOperand(from));
815 } else {
816 ASSERT(to->IsDoubleStackSlot() && from->IsDoubleStackSlot());
817 __ movdbl(xmm_scratch, ToOperand(from));
818 __ movdbl(ToOperand(to), xmm_scratch);
819 }
820 }
821
822 if (destroys_cpu_scratch) {
823 __ mov(cpu_scratch, Operand(ebp, -kPointerSize));
824 }
825 } 623 }
826 624
827 625
828 void LCodeGen::DoGap(LGap* gap) { 626 void LCodeGen::DoGap(LGap* gap) {
829 for (int i = LGap::FIRST_INNER_POSITION; 627 for (int i = LGap::FIRST_INNER_POSITION;
830 i <= LGap::LAST_INNER_POSITION; 628 i <= LGap::LAST_INNER_POSITION;
831 i++) { 629 i++) {
832 LGap::InnerPosition inner_pos = static_cast<LGap::InnerPosition>(i); 630 LGap::InnerPosition inner_pos = static_cast<LGap::InnerPosition>(i);
833 LParallelMove* move = gap->GetParallelMove(inner_pos); 631 LParallelMove* move = gap->GetParallelMove(inner_pos);
834 if (move != NULL) DoParallelMove(move); 632 if (move != NULL) DoParallelMove(move);
(...skipping 2808 matching lines...) Expand 10 before | Expand all | Expand 10 after
3643 ASSERT(osr_pc_offset_ == -1); 3441 ASSERT(osr_pc_offset_ == -1);
3644 osr_pc_offset_ = masm()->pc_offset(); 3442 osr_pc_offset_ = masm()->pc_offset();
3645 } 3443 }
3646 3444
3647 3445
3648 #undef __ 3446 #undef __
3649 3447
3650 } } // namespace v8::internal 3448 } } // namespace v8::internal
3651 3449
3652 #endif // V8_TARGET_ARCH_IA32 3450 #endif // V8_TARGET_ARCH_IA32
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698