OLD | NEW |
---|---|
1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2009 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 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
64 ASSERT(cgen != NULL); | 64 ASSERT(cgen != NULL); |
65 ASSERT(cgen_ == NULL); | 65 ASSERT(cgen_ == NULL); |
66 cgen_ = cgen; | 66 cgen_ = cgen; |
67 masm_ = cgen->masm(); | 67 masm_ = cgen->masm(); |
68 direction_ = direction; | 68 direction_ = direction; |
69 } | 69 } |
70 | 70 |
71 | 71 |
72 void JumpTarget::Unuse() { | 72 void JumpTarget::Unuse() { |
73 ASSERT(!is_linked()); | 73 ASSERT(!is_linked()); |
74 #ifdef DEBUG | |
75 for (int i = 0; i < reaching_frames_.length(); i++) { | 74 for (int i = 0; i < reaching_frames_.length(); i++) { |
76 ASSERT(reaching_frames_[i] == NULL); | 75 delete reaching_frames_[i]; |
Kasper Lund
2009/03/12 14:45:00
Do you want to NULL them out too in case the JumpT
Kevin Millikin (Chromium)
2009/03/12 14:53:51
Maybe it's safer (in the face of changes). Right
| |
77 } | 76 } |
78 #endif | |
79 delete entry_frame_; | 77 delete entry_frame_; |
80 | |
81 Reset(); | 78 Reset(); |
82 } | 79 } |
83 | 80 |
84 | 81 |
85 void JumpTarget::Reset() { | 82 void JumpTarget::Reset() { |
86 reaching_frames_.Clear(); | 83 reaching_frames_.Clear(); |
87 merge_labels_.Clear(); | 84 merge_labels_.Clear(); |
88 entry_frame_ = NULL; | 85 entry_frame_ = NULL; |
89 entry_label_.Unuse(); | 86 entry_label_.Unuse(); |
90 is_bound_ = false; | 87 is_bound_ = false; |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
136 return right; | 133 return right; |
137 } | 134 } |
138 } | 135 } |
139 | 136 |
140 // Otherwise they are incompatible and we will reallocate them. | 137 // Otherwise they are incompatible and we will reallocate them. |
141 return NULL; | 138 return NULL; |
142 } | 139 } |
143 | 140 |
144 | 141 |
145 void JumpTarget::ComputeEntryFrame(int mergable_elements) { | 142 void JumpTarget::ComputeEntryFrame(int mergable_elements) { |
146 // Given: a collection of frames reaching by forward CFG edges | 143 // Given: a collection of frames reaching by forward CFG edges and |
147 // (including the code generator's current frame) and the | 144 // the directionality of the block. Compute: an entry frame for the |
148 // directionality of the block. Compute: an entry frame for the | |
149 // block. | 145 // block. |
150 | 146 |
151 // Choose an initial frame, either the code generator's current | 147 // Choose an initial frame. |
152 // frame if there is one, or the first reaching frame if not. | 148 VirtualFrame* initial_frame = reaching_frames_[0]; |
153 VirtualFrame* initial_frame = cgen_->frame(); | |
154 int start_index = 0; // Begin iteration with the 1st reaching frame. | |
155 if (initial_frame == NULL) { | |
156 initial_frame = reaching_frames_[0]; | |
157 start_index = 1; // Begin iteration with the 2nd reaching frame. | |
158 } | |
159 | 149 |
160 // A list of pointers to frame elements in the entry frame. NULL | 150 // A list of pointers to frame elements in the entry frame. NULL |
161 // indicates that the element has not yet been determined. | 151 // indicates that the element has not yet been determined. |
162 int length = initial_frame->elements_.length(); | 152 int length = initial_frame->elements_.length(); |
163 List<FrameElement*> elements(length); | 153 List<FrameElement*> elements(length); |
164 | 154 |
165 // Convert the number of mergable elements (counted from the top | 155 // Convert the number of mergable elements (counted from the top |
166 // down) to a frame high-water mark (counted from the bottom up). | 156 // down) to a frame high-water mark (counted from the bottom up). |
167 // Elements strictly above the high-water index will be mergable in | 157 // Elements strictly above the high-water index will be mergable in |
168 // entry frames for bidirectional jump targets. | 158 // entry frames for bidirectional jump targets. |
169 int high_water_mark = (mergable_elements == kAllElements) | 159 int high_water_mark = (mergable_elements == kAllElements) |
170 ? VirtualFrame::kIllegalIndex // All frame indices are above this. | 160 ? VirtualFrame::kIllegalIndex // All frame indices are above this. |
171 : length - mergable_elements - 1; // Top index if m_e == 0. | 161 : length - mergable_elements - 1; // Top index if m_e == 0. |
172 | 162 |
173 // Initially populate the list of elements based on the initial | 163 // Initially populate the list of elements based on the initial |
174 // frame. | 164 // frame. |
175 for (int i = 0; i < length; i++) { | 165 for (int i = 0; i < length; i++) { |
176 FrameElement element = initial_frame->elements_[i]; | 166 FrameElement element = initial_frame->elements_[i]; |
177 // We do not allow copies or constants in bidirectional frames. | 167 // We do not allow copies or constants in bidirectional frames. |
178 if (direction_ == BIDIRECTIONAL && | 168 if (direction_ == BIDIRECTIONAL && |
179 i > high_water_mark && | 169 i > high_water_mark && |
180 (element.is_constant() || element.is_copy())) { | 170 (element.is_constant() || element.is_copy())) { |
181 elements.Add(NULL); | 171 elements.Add(NULL); |
182 } else { | 172 } else { |
183 elements.Add(&initial_frame->elements_[i]); | 173 elements.Add(&initial_frame->elements_[i]); |
184 } | 174 } |
185 } | 175 } |
186 | 176 |
187 // Compute elements based on the other reaching frames. | 177 // Compute elements based on the other reaching frames. |
188 if (start_index < reaching_frames_.length()) { | 178 if (reaching_frames_.length() > 1) { |
189 for (int i = 0; i < length; i++) { | 179 for (int i = 0; i < length; i++) { |
190 for (int j = start_index; j < reaching_frames_.length(); j++) { | 180 for (int j = 1; j < reaching_frames_.length(); j++) { |
191 FrameElement* element = elements[i]; | 181 FrameElement* element = elements[i]; |
192 | 182 |
193 // Element computation is monotonic: new information will not | 183 // Element computation is monotonic: new information will not |
194 // change our decision about undetermined or invalid elements. | 184 // change our decision about undetermined or invalid elements. |
195 if (element == NULL || !element->is_valid()) break; | 185 if (element == NULL || !element->is_valid()) break; |
196 | 186 |
197 elements[i] = Combine(element, &reaching_frames_[j]->elements_[i]); | 187 elements[i] = Combine(element, &reaching_frames_[j]->elements_[i]); |
198 } | 188 } |
199 } | 189 } |
200 } | 190 } |
(...skipping 18 matching lines...) Expand all Loading... | |
219 | 209 |
220 | 210 |
221 // Copy the already-determined frame elements to the entry frame, | 211 // Copy the already-determined frame elements to the entry frame, |
222 // and allocate any still-undetermined frame elements to registers | 212 // and allocate any still-undetermined frame elements to registers |
223 // or memory, from the top down. | 213 // or memory, from the top down. |
224 for (int i = length - 1; i >= 0; i--) { | 214 for (int i = length - 1; i >= 0; i--) { |
225 if (elements[i] == NULL) { | 215 if (elements[i] == NULL) { |
226 // If the value is synced on all frames, put it in memory. This | 216 // If the value is synced on all frames, put it in memory. This |
227 // costs nothing at the merge code but will incur a | 217 // costs nothing at the merge code but will incur a |
228 // memory-to-register move when the value is needed later. | 218 // memory-to-register move when the value is needed later. |
229 bool is_synced = initial_frame->elements_[i].is_synced(); | 219 bool is_synced = true; |
230 int j = start_index; | 220 for (int j = 0; is_synced && j < reaching_frames_.length(); j++) { |
231 while (is_synced && j < reaching_frames_.length()) { | |
232 is_synced = reaching_frames_[j]->elements_[i].is_synced(); | 221 is_synced = reaching_frames_[j]->elements_[i].is_synced(); |
233 j++; | |
234 } | 222 } |
223 | |
235 // There is nothing to be done if the elements are all synced. | 224 // There is nothing to be done if the elements are all synced. |
236 // It is already recorded as a memory element. | 225 // It is already recorded as a memory element. |
237 if (is_synced) continue; | 226 if (is_synced) continue; |
238 | 227 |
239 // Choose an available register. Prefer ones that the element | 228 // Choose an available register. Prefer ones that the element |
240 // is already occupying on some reaching frame. | 229 // is already occupying on some reaching frame. |
241 RegisterFile candidate_registers; | 230 RegisterFile candidate_registers; |
242 int max_count = kMinInt; | 231 int max_count = kMinInt; |
243 int best_reg_code = no_reg.code_; | 232 int best_reg_code = no_reg.code_; |
244 | 233 |
245 // Consider the initial frame. | 234 for (int j = 0; j < reaching_frames_.length(); j++) { |
246 FrameElement element = initial_frame->elements_[i]; | 235 FrameElement element = reaching_frames_[j]->elements_[i]; |
247 if (element.is_register() && | |
248 !frame_registers.is_used(element.reg())) { | |
249 candidate_registers.Use(element.reg()); | |
250 max_count = 1; | |
251 best_reg_code = element.reg().code(); | |
252 } | |
253 // Consider the other frames. | |
254 for (int j = start_index; j < reaching_frames_.length(); j++) { | |
255 element = reaching_frames_[j]->elements_[i]; | |
256 if (element.is_register() && | 236 if (element.is_register() && |
257 !frame_registers.is_used(element.reg())) { | 237 !frame_registers.is_used(element.reg())) { |
258 candidate_registers.Use(element.reg()); | 238 candidate_registers.Use(element.reg()); |
259 if (candidate_registers.count(element.reg()) > max_count) { | 239 if (candidate_registers.count(element.reg()) > max_count) { |
260 max_count = candidate_registers.count(element.reg()); | 240 max_count = candidate_registers.count(element.reg()); |
261 best_reg_code = element.reg().code(); | 241 best_reg_code = element.reg().code(); |
262 } | 242 } |
263 } | 243 } |
264 } | 244 } |
265 // If there was no preferred choice consider any free register. | 245 // If there was no preferred choice consider any free register. |
(...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
582 } else { | 562 } else { |
583 JumpTarget::Branch(cc, hint); | 563 JumpTarget::Branch(cc, hint); |
584 } | 564 } |
585 } | 565 } |
586 | 566 |
587 | 567 |
588 void BreakTarget::Bind(int mergable_elements) { | 568 void BreakTarget::Bind(int mergable_elements) { |
589 #ifdef DEBUG | 569 #ifdef DEBUG |
590 ASSERT(mergable_elements == kAllElements); | 570 ASSERT(mergable_elements == kAllElements); |
591 ASSERT(cgen_ != NULL); | 571 ASSERT(cgen_ != NULL); |
572 // All the forward-reaching frames should have been adjusted at the | |
573 // jumps to this target. | |
592 for (int i = 0; i < reaching_frames_.length(); i++) { | 574 for (int i = 0; i < reaching_frames_.length(); i++) { |
593 ASSERT(reaching_frames_[i]->height() == expected_height_); | 575 ASSERT(reaching_frames_[i] == NULL || |
576 reaching_frames_[i]->height() == expected_height_); | |
594 } | 577 } |
595 #endif | 578 #endif |
596 | 579 // This is a break target so we drop leftover statement state from |
597 // This is a break target so drop leftover statement state from the | 580 // the frame before merging, even on the fall through. This is |
598 // frame before merging. | 581 // because we can bind the return target with state on the frame. |
599 if (cgen_->has_valid_frame()) { | 582 if (cgen_->has_valid_frame()) { |
600 int count = cgen_->frame()->height() - expected_height_; | 583 cgen_->frame()->ForgetElements(cgen_->frame()->height() - expected_height_); |
601 cgen_->frame()->ForgetElements(count); | |
602 } | 584 } |
603 JumpTarget::Bind(mergable_elements); | 585 JumpTarget::Bind(mergable_elements); |
604 } | 586 } |
605 | 587 |
606 | 588 |
607 // ------------------------------------------------------------------------- | 589 // ------------------------------------------------------------------------- |
608 // ShadowTarget implementation. | 590 // ShadowTarget implementation. |
609 | 591 |
610 ShadowTarget::ShadowTarget(BreakTarget* shadowed) { | 592 ShadowTarget::ShadowTarget(BreakTarget* shadowed) { |
611 ASSERT(shadowed != NULL); | 593 ASSERT(shadowed != NULL); |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
648 temp.CopyTo(this); | 630 temp.CopyTo(this); |
649 temp.Reset(); // So the destructor does not deallocate virtual frames. | 631 temp.Reset(); // So the destructor does not deallocate virtual frames. |
650 | 632 |
651 #ifdef DEBUG | 633 #ifdef DEBUG |
652 is_shadowing_ = false; | 634 is_shadowing_ = false; |
653 #endif | 635 #endif |
654 } | 636 } |
655 | 637 |
656 | 638 |
657 } } // namespace v8::internal | 639 } } // namespace v8::internal |
OLD | NEW |