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 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 94 | 94 |
| 95 FrameElement* JumpTarget::Combine(FrameElement* left, FrameElement* right) { | 95 FrameElement* JumpTarget::Combine(FrameElement* left, FrameElement* right) { |
| 96 // Given a pair of non-null frame element pointers, return one of | 96 // Given a pair of non-null frame element pointers, return one of |
| 97 // them as an entry frame candidate or null if they are | 97 // them as an entry frame candidate or null if they are |
| 98 // incompatible. | 98 // incompatible. |
| 99 | 99 |
| 100 // If either is invalid, the result is. | 100 // If either is invalid, the result is. |
| 101 if (!left->is_valid()) return left; | 101 if (!left->is_valid()) return left; |
| 102 if (!right->is_valid()) return right; | 102 if (!right->is_valid()) return right; |
| 103 | 103 |
| 104 // If they have the same value, the result is the same. If either | 104 // If they have the exact same location, the result is in that |
| 105 // is unsynced, the result is. | 105 // location, otherwise we reallocate. If either is unsynced, the |
| 106 // result is. The result static type is the merge of the static | |
| 107 // types. It's safe to set it on one of the frame elements, and | |
| 108 // harmless too (because we are only going to merge the reaching | |
| 109 // frames and will ensure that the types are coherent, and changing | |
| 110 // the static type does not emit code). | |
| 106 | 111 |
| 107 if (left->is_memory() && right->is_memory()) return left; | 112 StaticType type = left->static_type().merge(right->static_type()); |
| 113 if (left->is_memory() && right->is_memory()) { | |
| 114 left->set_static_type(type); | |
| 115 return left; | |
| 116 } | |
| 108 | 117 |
| 109 if (left->is_register() && right->is_register() && | 118 if (left->is_register() && right->is_register() && |
|
Lasse Reichstein
2009/05/12 14:45:38
This function looks like a lot of duplicated code.
| |
| 110 left->reg().is(right->reg())) { | 119 left->reg().is(right->reg())) { |
| 111 if (!left->is_synced()) { | 120 if (!left->is_synced()) { |
| 121 left->set_static_type(type); | |
| 112 return left; | 122 return left; |
| 113 } else { | 123 } else { |
| 124 right->set_static_type(type); | |
| 114 return right; | 125 return right; |
| 115 } | 126 } |
| 116 } | 127 } |
| 117 | 128 |
| 118 if (left->is_constant() && | 129 if (left->is_constant() && |
| 119 right->is_constant() && | 130 right->is_constant() && |
| 120 left->handle().is_identical_to(right->handle())) { | 131 left->handle().is_identical_to(right->handle())) { |
| 121 if (!left->is_synced()) { | 132 if (!left->is_synced()) { |
| 133 left->set_static_type(type); | |
| 122 return left; | 134 return left; |
| 123 } else { | 135 } else { |
| 136 right->set_static_type(type); | |
| 124 return right; | 137 return right; |
| 125 } | 138 } |
| 126 } | 139 } |
| 127 | 140 |
| 128 if (left->is_copy() && | 141 if (left->is_copy() && |
| 129 right->is_copy() && | 142 right->is_copy() && |
| 130 left->index() == right->index()) { | 143 left->index() == right->index()) { |
| 131 if (!left->is_synced()) { | 144 if (!left->is_synced()) { |
| 145 left->set_static_type(type); | |
| 132 return left; | 146 return left; |
| 133 } else { | 147 } else { |
| 148 right->set_static_type(type); | |
| 134 return right; | 149 return right; |
| 135 } | 150 } |
| 136 } | 151 } |
| 137 | 152 |
| 138 // Otherwise they are incompatible and we will reallocate them. | 153 // Otherwise they are incompatible and we will reallocate them. |
| 139 return NULL; | 154 return NULL; |
| 140 } | 155 } |
| 141 | 156 |
| 142 | 157 |
| 143 void JumpTarget::ComputeEntryFrame(int mergable_elements) { | 158 void JumpTarget::ComputeEntryFrame(int mergable_elements) { |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 157 // down) to a frame high-water mark (counted from the bottom up). | 172 // down) to a frame high-water mark (counted from the bottom up). |
| 158 // Elements strictly above the high-water index will be mergable in | 173 // Elements strictly above the high-water index will be mergable in |
| 159 // entry frames for bidirectional jump targets. | 174 // entry frames for bidirectional jump targets. |
| 160 int high_water_mark = (mergable_elements == kAllElements) | 175 int high_water_mark = (mergable_elements == kAllElements) |
| 161 ? VirtualFrame::kIllegalIndex // All frame indices are above this. | 176 ? VirtualFrame::kIllegalIndex // All frame indices are above this. |
| 162 : length - mergable_elements - 1; // Top index if m_e == 0. | 177 : length - mergable_elements - 1; // Top index if m_e == 0. |
| 163 | 178 |
| 164 // Initially populate the list of elements based on the initial | 179 // Initially populate the list of elements based on the initial |
| 165 // frame. | 180 // frame. |
| 166 for (int i = 0; i < length; i++) { | 181 for (int i = 0; i < length; i++) { |
| 167 FrameElement element = initial_frame->elements_[i]; | 182 FrameElement element = initial_frame->elements_[i]; |
|
Lasse Reichstein
2009/05/12 14:45:38
If we look this element up again later, would it p
| |
| 168 // We do not allow copies or constants in bidirectional frames. | 183 // We do not allow copies or constants in bidirectional frames. All |
| 169 if (direction_ == BIDIRECTIONAL && i > high_water_mark && | 184 // elements above the water mark on bidirectional frames have |
| 170 (element.is_constant() || element.is_copy())) { | 185 // unknown static types. |
| 171 elements.Add(NULL); | 186 if (direction_ == BIDIRECTIONAL && i > high_water_mark) { |
| 172 } else { | 187 if (element.is_constant() || element.is_copy()) { |
| 173 elements.Add(&initial_frame->elements_[i]); | 188 elements.Add(NULL); |
| 189 continue; | |
| 190 } | |
| 191 // It's safe to change the static type on the initial frame | |
| 192 // element, see comment in JumpTarget::Combine. | |
| 193 initial_frame->elements_[i].set_static_type(StaticType::unknown()); | |
| 174 } | 194 } |
| 195 elements.Add(&initial_frame->elements_[i]); | |
| 175 } | 196 } |
| 176 | 197 |
| 177 // Compute elements based on the other reaching frames. | 198 // Compute elements based on the other reaching frames. |
| 178 if (reaching_frames_.length() > 1) { | 199 if (reaching_frames_.length() > 1) { |
| 179 for (int i = 0; i < length; i++) { | 200 for (int i = 0; i < length; i++) { |
| 180 for (int j = 1; j < reaching_frames_.length(); j++) { | 201 for (int j = 1; j < reaching_frames_.length(); j++) { |
| 181 FrameElement* element = elements[i]; | 202 FrameElement* element = elements[i]; |
| 182 | 203 |
| 183 // Element computation is monotonic: new information will not | 204 // Element computation is monotonic: new information will not |
| 184 // change our decision about undetermined or invalid elements. | 205 // change our decision about undetermined or invalid elements. |
| 185 if (element == NULL || !element->is_valid()) break; | 206 if (element == NULL || !element->is_valid()) break; |
| 186 | 207 |
| 187 elements[i] = Combine(element, &reaching_frames_[j]->elements_[i]); | 208 elements[i] = Combine(element, &reaching_frames_[j]->elements_[i]); |
|
Lasse Reichstein
2009/05/12 14:45:38
Why do we read the element on each round of the in
| |
| 188 } | 209 } |
| 189 } | 210 } |
| 190 } | 211 } |
| 191 | 212 |
| 192 // Build the new frame. A freshly allocated frame has memory elements | 213 // Build the new frame. A freshly allocated frame has memory elements |
| 193 // for the parameters and some platform-dependent elements (e.g., | 214 // for the parameters and some platform-dependent elements (e.g., |
| 194 // return address). Replace those first. | 215 // return address). Replace those first. |
| 195 entry_frame_ = new VirtualFrame(cgen_); | 216 entry_frame_ = new VirtualFrame(cgen_); |
| 196 int index = 0; | 217 int index = 0; |
| 197 for (; index < entry_frame_->elements_.length(); index++) { | 218 for (; index < entry_frame_->elements_.length(); index++) { |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 222 } else if (elements[index]->is_copy()) { | 243 } else if (elements[index]->is_copy()) { |
| 223 entry_frame_->elements_[elements[index]->index()].set_copied(); | 244 entry_frame_->elements_[elements[index]->index()].set_copied(); |
| 224 } | 245 } |
| 225 } | 246 } |
| 226 } | 247 } |
| 227 | 248 |
| 228 // Allocate any still-undetermined frame elements to registers or | 249 // Allocate any still-undetermined frame elements to registers or |
| 229 // memory, from the top down. | 250 // memory, from the top down. |
| 230 for (int i = length - 1; i >= 0; i--) { | 251 for (int i = length - 1; i >= 0; i--) { |
| 231 if (elements[i] == NULL) { | 252 if (elements[i] == NULL) { |
| 253 // Loop over all the reaching frames to check whether the element | |
| 254 // is synced on all frames, to count the registers it occupies, | |
| 255 // and to compute a merged static type. | |
| 256 bool is_synced = true; | |
| 257 RegisterFile candidate_registers; | |
| 258 int best_count = kMinInt; | |
| 259 int best_reg_code = no_reg.code_; | |
| 260 | |
| 261 StaticType type; // Initially invalid. | |
| 262 if (direction_ != BIDIRECTIONAL || i < high_water_mark) { | |
| 263 type = reaching_frames_[0]->elements_[i].static_type(); | |
| 264 } | |
| 265 | |
| 266 for (int j = 0; j < reaching_frames_.length(); j++) { | |
| 267 FrameElement element = reaching_frames_[j]->elements_[i]; | |
| 268 is_synced = is_synced && element.is_synced(); | |
| 269 if (element.is_register() && !entry_frame_->is_used(element.reg())) { | |
| 270 // Count the register occurrence and remember it if better | |
| 271 // than the previous best. | |
| 272 candidate_registers.Use(element.reg()); | |
| 273 if (candidate_registers.count(element.reg()) > best_count) { | |
| 274 best_count = candidate_registers.count(element.reg()); | |
| 275 best_reg_code = element.reg().code(); | |
| 276 } | |
| 277 } | |
| 278 type = type.merge(element.static_type()); | |
| 279 } | |
| 280 | |
| 232 // If the value is synced on all frames, put it in memory. This | 281 // If the value is synced on all frames, put it in memory. This |
| 233 // costs nothing at the merge code but will incur a | 282 // costs nothing at the merge code but will incur a |
| 234 // memory-to-register move when the value is needed later. | 283 // memory-to-register move when the value is needed later. |
| 235 bool is_synced = true; | 284 if (is_synced) { |
| 236 for (int j = 0; is_synced && j < reaching_frames_.length(); j++) { | 285 // Already recorded as a memory element. |
| 237 is_synced = reaching_frames_[j]->elements_[i].is_synced(); | 286 entry_frame_->elements_[i].set_static_type(type); |
| 287 continue; | |
| 238 } | 288 } |
| 239 | 289 |
| 240 // There is nothing to be done if the elements are all synced. | 290 // Try to put it in a register. If there was no best choice |
| 241 // It is already recorded as a memory element. | 291 // consider any free register. |
| 242 if (is_synced) continue; | |
| 243 | |
| 244 // Choose an available register. Prefer ones that the element | |
| 245 // is already occupying on some reaching frame. | |
| 246 RegisterFile candidate_registers; | |
| 247 int max_count = kMinInt; | |
| 248 int best_reg_code = no_reg.code_; | |
| 249 | |
| 250 for (int j = 0; j < reaching_frames_.length(); j++) { | |
| 251 FrameElement element = reaching_frames_[j]->elements_[i]; | |
| 252 if (element.is_register() && | |
| 253 !entry_frame_->is_used(element.reg())) { | |
| 254 candidate_registers.Use(element.reg()); | |
| 255 if (candidate_registers.count(element.reg()) > max_count) { | |
| 256 max_count = candidate_registers.count(element.reg()); | |
| 257 best_reg_code = element.reg().code(); | |
| 258 } | |
| 259 } | |
| 260 } | |
| 261 // If there was no preferred choice consider any free register. | |
| 262 if (best_reg_code == no_reg.code_) { | 292 if (best_reg_code == no_reg.code_) { |
| 263 for (int j = 0; j < kNumRegisters; j++) { | 293 for (int j = 0; j < kNumRegisters; j++) { |
| 264 if (!entry_frame_->is_used(j) && !RegisterAllocator::IsReserved(j)) { | 294 if (!entry_frame_->is_used(j) && !RegisterAllocator::IsReserved(j)) { |
| 265 best_reg_code = j; | 295 best_reg_code = j; |
| 266 break; | 296 break; |
| 267 } | 297 } |
| 268 } | 298 } |
| 269 } | 299 } |
| 270 | 300 |
| 271 if (best_reg_code != no_reg.code_) { | 301 if (best_reg_code == no_reg.code_) { |
| 302 // If there was no register found, the element is already | |
| 303 // recorded as in memory. | |
| 304 entry_frame_->elements_[i].set_static_type(type); | |
| 305 } else { | |
| 272 // If there was a register choice, use it. Preserve the copied | 306 // If there was a register choice, use it. Preserve the copied |
| 273 // flag on the element. | 307 // flag on the element. Set the static type as computed. |
| 274 bool is_copied = entry_frame_->elements_[i].is_copied(); | 308 bool is_copied = entry_frame_->elements_[i].is_copied(); |
| 275 Register reg = { best_reg_code }; | 309 Register reg = { best_reg_code }; |
| 276 entry_frame_->elements_[i] = | 310 entry_frame_->elements_[i] = |
| 277 FrameElement::RegisterElement(reg, | 311 FrameElement::RegisterElement(reg, |
| 278 FrameElement::NOT_SYNCED); | 312 FrameElement::NOT_SYNCED); |
| 279 if (is_copied) entry_frame_->elements_[i].set_copied(); | 313 if (is_copied) entry_frame_->elements_[i].set_copied(); |
| 314 entry_frame_->elements_[i].set_static_type(type); | |
| 280 entry_frame_->register_locations_[best_reg_code] = i; | 315 entry_frame_->register_locations_[best_reg_code] = i; |
| 281 } | 316 } |
| 282 // If there was no register found, the element is already | |
| 283 // recorded as in memory. | |
| 284 } | |
| 285 } | |
| 286 | |
| 287 // Set the static type of frame elements. | |
| 288 for (int i = 0; i < length; i++) { | |
| 289 FrameElement* current = &entry_frame_->elements_[i]; | |
| 290 if (direction_ == BIDIRECTIONAL && i >= high_water_mark) { | |
| 291 current->set_static_type(StaticType::unknown()); | |
| 292 } else { | |
| 293 StaticType merged_type = reaching_frames_[0]->elements_[i].static_type(); | |
| 294 for (int j = 1, n = reaching_frames_.length(); | |
| 295 !merged_type.is_unknown() && j < n; | |
| 296 j++) { | |
| 297 merged_type = | |
| 298 merged_type.merge(reaching_frames_[j]->elements_[i].static_type()); | |
| 299 } | |
| 300 current->set_static_type(merged_type); | |
| 301 } | 317 } |
| 302 } | 318 } |
| 303 | 319 |
| 304 // Fill in the other fields of the entry frame. | 320 // Fill in the other fields of the entry frame. |
| 305 entry_frame_->local_count_ = initial_frame->local_count_; | 321 entry_frame_->local_count_ = initial_frame->local_count_; |
| 306 entry_frame_->frame_pointer_ = initial_frame->frame_pointer_; | 322 entry_frame_->frame_pointer_ = initial_frame->frame_pointer_; |
| 307 | 323 |
| 308 // The stack pointer is at the highest synced element or the base of | 324 // The stack pointer is at the highest synced element or the base of |
| 309 // the expression stack. | 325 // the expression stack. |
| 310 int stack_pointer = length - 1; | 326 int stack_pointer = length - 1; |
| (...skipping 419 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 730 temp.CopyTo(this); | 746 temp.CopyTo(this); |
| 731 temp.Reset(); // So the destructor does not deallocate virtual frames. | 747 temp.Reset(); // So the destructor does not deallocate virtual frames. |
| 732 | 748 |
| 733 #ifdef DEBUG | 749 #ifdef DEBUG |
| 734 is_shadowing_ = false; | 750 is_shadowing_ = false; |
| 735 #endif | 751 #endif |
| 736 } | 752 } |
| 737 | 753 |
| 738 | 754 |
| 739 } } // namespace v8::internal | 755 } } // namespace v8::internal |
| OLD | NEW |