Chromium Code Reviews| 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 |