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 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
50 | 50 |
51 | 51 |
52 // When cloned, a frame is a deep copy of the original. | 52 // When cloned, a frame is a deep copy of the original. |
53 VirtualFrame::VirtualFrame(VirtualFrame* original) | 53 VirtualFrame::VirtualFrame(VirtualFrame* original) |
54 : cgen_(original->cgen_), | 54 : cgen_(original->cgen_), |
55 masm_(original->masm_), | 55 masm_(original->masm_), |
56 elements_(original->elements_.length()), | 56 elements_(original->elements_.length()), |
57 parameter_count_(original->parameter_count_), | 57 parameter_count_(original->parameter_count_), |
58 local_count_(original->local_count_), | 58 local_count_(original->local_count_), |
59 stack_pointer_(original->stack_pointer_), | 59 stack_pointer_(original->stack_pointer_), |
60 frame_pointer_(original->frame_pointer_), | 60 frame_pointer_(original->frame_pointer_) { |
61 frame_registers_(original->frame_registers_) { | |
62 // Copy all the elements from the original. | 61 // Copy all the elements from the original. |
63 for (int i = 0; i < original->elements_.length(); i++) { | 62 for (int i = 0; i < original->elements_.length(); i++) { |
64 elements_.Add(original->elements_[i]); | 63 elements_.Add(original->elements_[i]); |
65 } | 64 } |
66 for (int i = 0; i < kNumRegisters; i++) { | 65 for (int i = 0; i < kNumRegisters; i++) { |
67 register_locations_[i] = original->register_locations_[i]; | 66 register_locations_[i] = original->register_locations_[i]; |
68 } | 67 } |
69 } | 68 } |
70 | 69 |
71 | 70 |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
145 | 144 |
146 for (int i = 0; i < count; i++) { | 145 for (int i = 0; i < count; i++) { |
147 FrameElement last = elements_.RemoveLast(); | 146 FrameElement last = elements_.RemoveLast(); |
148 if (last.is_register()) { | 147 if (last.is_register()) { |
149 // A hack to properly count register references for the code | 148 // A hack to properly count register references for the code |
150 // generator's current frame and also for other frames. The | 149 // generator's current frame and also for other frames. The |
151 // same code appears in PrepareMergeTo. | 150 // same code appears in PrepareMergeTo. |
152 if (cgen_->frame() == this) { | 151 if (cgen_->frame() == this) { |
153 Unuse(last.reg()); | 152 Unuse(last.reg()); |
154 } else { | 153 } else { |
155 frame_registers_.Unuse(last.reg()); | |
156 register_locations_[last.reg().code()] = kIllegalIndex; | 154 register_locations_[last.reg().code()] = kIllegalIndex; |
157 } | 155 } |
158 } | 156 } |
159 } | 157 } |
160 } | 158 } |
161 | 159 |
162 | 160 |
163 void VirtualFrame::Use(Register reg, int index) { | 161 void VirtualFrame::Use(Register reg, int index) { |
164 ASSERT(frame_registers_.count(reg) == 0); | |
165 ASSERT(register_locations_[reg.code()] == kIllegalIndex); | 162 ASSERT(register_locations_[reg.code()] == kIllegalIndex); |
166 register_locations_[reg.code()] = index; | 163 register_locations_[reg.code()] = index; |
167 frame_registers_.Use(reg); | |
168 cgen_->allocator()->Use(reg); | 164 cgen_->allocator()->Use(reg); |
169 } | 165 } |
170 | 166 |
171 | 167 |
172 void VirtualFrame::Unuse(Register reg) { | 168 void VirtualFrame::Unuse(Register reg) { |
173 ASSERT(frame_registers_.count(reg) == 1); | |
174 ASSERT(register_locations_[reg.code()] != kIllegalIndex); | 169 ASSERT(register_locations_[reg.code()] != kIllegalIndex); |
175 register_locations_[reg.code()] = kIllegalIndex; | 170 register_locations_[reg.code()] = kIllegalIndex; |
176 frame_registers_.Unuse(reg); | |
177 cgen_->allocator()->Unuse(reg); | 171 cgen_->allocator()->Unuse(reg); |
178 } | 172 } |
179 | 173 |
180 | 174 |
181 void VirtualFrame::Spill(Register target) { | 175 void VirtualFrame::Spill(Register target) { |
182 if (!frame_registers_.is_used(target)) return; | 176 if (is_used(target)) { |
183 for (int i = 0; i < elements_.length(); i++) { | 177 SpillElementAt(register_index(target)); |
184 if (elements_[i].is_register() && elements_[i].reg().is(target)) { | |
185 SpillElementAt(i); | |
186 } | |
187 } | 178 } |
188 } | 179 } |
189 | 180 |
190 | 181 |
191 // Spill any register if possible, making its external reference count zero. | 182 // Spill any register if possible, making its external reference count zero. |
192 Register VirtualFrame::SpillAnyRegister() { | 183 Register VirtualFrame::SpillAnyRegister() { |
193 // Find the leftmost (ordered by register code), least | 184 // Find the leftmost (ordered by register code), least |
194 // internally-referenced register whose internal reference count matches | 185 // internally-referenced register whose internal reference count matches |
195 // its external reference count (so that spilling it from the frame frees | 186 // its external reference count (so that spilling it from the frame frees |
196 // it for use). | 187 // it for use). |
197 int min_count = kMaxInt; | 188 // This function must be called with no free registers - all counts |
198 int best_register_code = no_reg.code_; | 189 // in the CodeGenerator's Allocator must be above 0. |
Kevin Millikin (Chromium)
2009/03/25 09:54:11
I don't like this comment. It's not really a true
William Hesse
2012/05/07 09:35:42
Done.
| |
199 | |
200 for (int i = 0; i < kNumRegisters; i++) { | 190 for (int i = 0; i < kNumRegisters; i++) { |
201 int count = frame_registers_.count(i); | 191 if (is_used(i) && cgen_->allocator()->count(i) == 1) { |
202 if (count < min_count && count == cgen_->allocator()->count(i)) { | 192 Register result = { i }; |
203 min_count = count; | 193 Spill(result); |
204 best_register_code = i; | 194 ASSERT(!cgen_->allocator()->is_used(result)); |
195 return result; | |
205 } | 196 } |
206 } | 197 } |
207 | 198 return no_reg; |
208 Register result = { best_register_code }; | |
209 if (result.is_valid()) { | |
210 Spill(result); | |
211 ASSERT(!cgen_->allocator()->is_used(result)); | |
212 } | |
213 return result; | |
214 } | 199 } |
215 | 200 |
216 | 201 |
217 // Make the type of the element at a given index be MEMORY. | 202 // Make the type of the element at a given index be MEMORY. |
218 void VirtualFrame::SpillElementAt(int index) { | 203 void VirtualFrame::SpillElementAt(int index) { |
219 if (!elements_[index].is_valid()) return; | 204 if (!elements_[index].is_valid()) return; |
220 | 205 |
221 SyncElementAt(index); | 206 SyncElementAt(index); |
222 // The element is now in memory. Its copied flag is preserved. | 207 // The element is now in memory. Its copied flag is preserved. |
223 FrameElement new_element = FrameElement::MemoryElement(); | 208 FrameElement new_element = FrameElement::MemoryElement(); |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
272 // No code needs to be generated to move values to memory if | 257 // No code needs to be generated to move values to memory if |
273 // they are already synced. We perform those moves here, before | 258 // they are already synced. We perform those moves here, before |
274 // merging. | 259 // merging. |
275 if (source.is_register()) { | 260 if (source.is_register()) { |
276 // If the frame is the code generator's current frame, we have | 261 // If the frame is the code generator's current frame, we have |
277 // to decrement both the frame-internal and global register | 262 // to decrement both the frame-internal and global register |
278 // counts. | 263 // counts. |
279 if (cgen_->frame() == this) { | 264 if (cgen_->frame() == this) { |
280 Unuse(source.reg()); | 265 Unuse(source.reg()); |
281 } else { | 266 } else { |
282 frame_registers_.Unuse(source.reg()); | |
283 register_locations_[source.reg().code()] = kIllegalIndex; | 267 register_locations_[source.reg().code()] = kIllegalIndex; |
284 } | 268 } |
285 } | 269 } |
286 elements_[i] = target; | 270 elements_[i] = target; |
287 } else if (target.is_register() && !target.is_synced() && | 271 } else if (target.is_register() && !target.is_synced() && |
288 !source.is_memory()) { | 272 !source.is_memory()) { |
289 // If an element's target is a register that doesn't need to be | 273 // If an element's target is a register that doesn't need to be |
290 // synced, and the element is not in memory, then the sync state | 274 // synced, and the element is not in memory, then the sync state |
291 // of the element is irrelevant. We clear the sync bit. | 275 // of the element is irrelevant. We clear the sync bit. |
292 ASSERT(source.is_valid()); | 276 ASSERT(source.is_valid()); |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
383 && original.handle().is_identical_to(value->handle()); | 367 && original.handle().is_identical_to(value->handle()); |
384 if (same_register || same_constant) { | 368 if (same_register || same_constant) { |
385 value->Unuse(); | 369 value->Unuse(); |
386 return; | 370 return; |
387 } | 371 } |
388 | 372 |
389 InvalidateFrameSlotAt(frame_index); | 373 InvalidateFrameSlotAt(frame_index); |
390 | 374 |
391 FrameElement new_element; | 375 FrameElement new_element; |
392 if (value->is_register()) { | 376 if (value->is_register()) { |
393 // There are two cases depending no whether the register already | 377 if (is_used(value->reg())) { |
394 // occurs in the frame or not. | 378 // The register already appears on the frame. Either the existing |
395 if (register_count(value->reg()) == 0) { | 379 // register element, or the new element at frame_index, must be made |
396 Use(value->reg(), frame_index); | 380 // a copy. |
397 elements_[frame_index] = | 381 int i = register_index(value->reg()); |
398 FrameElement::RegisterElement(value->reg(), | |
399 FrameElement::NOT_SYNCED); | |
400 } else { | |
401 int i = 0; | |
402 for (; i < elements_.length(); i++) { | |
403 if (elements_[i].is_register() && elements_[i].reg().is(value->reg())) { | |
404 break; | |
405 } | |
406 } | |
407 ASSERT(i < elements_.length()); | |
408 | |
409 if (i < frame_index) { | 382 if (i < frame_index) { |
410 // The register backing store is lower in the frame than its copy. | 383 // The register FrameElement is lower in the frame than the new copy. |
411 elements_[frame_index] = CopyElementAt(i); | 384 elements_[frame_index] = CopyElementAt(i); |
412 } else { | 385 } else { |
413 // There was an early bailout for the case of setting a | 386 // There was an early bailout for the case of setting a |
414 // register element to itself. | 387 // register element to itself. |
415 ASSERT(i != frame_index); | 388 ASSERT(i != frame_index); |
416 elements_[frame_index] = elements_[i]; | 389 elements_[frame_index] = elements_[i]; |
417 elements_[i] = CopyElementAt(frame_index); | 390 elements_[i] = CopyElementAt(frame_index); |
418 if (elements_[frame_index].is_synced()) { | 391 if (elements_[frame_index].is_synced()) { |
419 elements_[i].set_sync(); | 392 elements_[i].set_sync(); |
420 } | 393 } |
421 elements_[frame_index].clear_sync(); | 394 elements_[frame_index].clear_sync(); |
422 register_locations_[value->reg().code()] = frame_index; | 395 register_locations_[value->reg().code()] = frame_index; |
423 for (int j = i + 1; j < elements_.length(); j++) { | 396 for (int j = i + 1; j < elements_.length(); j++) { |
424 if (elements_[j].is_copy() && elements_[j].index() == i) { | 397 if (elements_[j].is_copy() && elements_[j].index() == i) { |
425 elements_[j].set_index(frame_index); | 398 elements_[j].set_index(frame_index); |
426 } | 399 } |
427 } | 400 } |
428 } | 401 } |
402 } else { | |
403 // The register value->reg() was not already used on the frame. | |
404 Use(value->reg(), frame_index); | |
405 elements_[frame_index] = | |
406 FrameElement::RegisterElement(value->reg(), | |
407 FrameElement::NOT_SYNCED); | |
429 } | 408 } |
430 } else { | 409 } else { |
431 ASSERT(value->is_constant()); | 410 ASSERT(value->is_constant()); |
432 elements_[frame_index] = | 411 elements_[frame_index] = |
433 FrameElement::ConstantElement(value->handle(), | 412 FrameElement::ConstantElement(value->handle(), |
434 FrameElement::NOT_SYNCED); | 413 FrameElement::NOT_SYNCED); |
435 } | 414 } |
436 value->Unuse(); | 415 value->Unuse(); |
437 } | 416 } |
438 | 417 |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
490 // a different signature. | 469 // a different signature. |
491 UNREACHABLE(); | 470 UNREACHABLE(); |
492 break; | 471 break; |
493 } | 472 } |
494 PrepareForCall(spilled_args, dropped_args); | 473 PrepareForCall(spilled_args, dropped_args); |
495 return RawCallCodeObject(code, rmode); | 474 return RawCallCodeObject(code, rmode); |
496 } | 475 } |
497 | 476 |
498 | 477 |
499 void VirtualFrame::Push(Register reg) { | 478 void VirtualFrame::Push(Register reg) { |
500 FrameElement new_element; | 479 if (is_used(reg)) { |
501 if (register_count(reg) == 0) { | 480 elements_.Add(CopyElementAt(register_index(reg))); |
481 } else { | |
502 Use(reg, elements_.length()); | 482 Use(reg, elements_.length()); |
503 new_element = | 483 elements_.Add(FrameElement::RegisterElement(reg, FrameElement::NOT_SYNCED)); |
504 FrameElement::RegisterElement(reg, FrameElement::NOT_SYNCED); | |
505 } else { | |
506 for (int i = 0; i < elements_.length(); i++) { | |
507 FrameElement element = elements_[i]; | |
508 if (element.is_register() && element.reg().is(reg)) { | |
509 new_element = CopyElementAt(i); | |
510 break; | |
511 } | |
512 } | |
513 } | 484 } |
514 elements_.Add(new_element); | |
515 } | 485 } |
516 | 486 |
517 | 487 |
518 void VirtualFrame::Push(Handle<Object> value) { | 488 void VirtualFrame::Push(Handle<Object> value) { |
519 elements_.Add(FrameElement::ConstantElement(value, | 489 elements_.Add(FrameElement::ConstantElement(value, |
520 FrameElement::NOT_SYNCED)); | 490 FrameElement::NOT_SYNCED)); |
521 } | 491 } |
522 | 492 |
523 | 493 |
524 void VirtualFrame::Push(Result* result) { | 494 void VirtualFrame::Push(Result* result) { |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
562 #ifdef DEBUG | 532 #ifdef DEBUG |
563 // These are sanity checks in debug builds, but we do not need to | 533 // These are sanity checks in debug builds, but we do not need to |
564 // use them to distinguish frames at merge points. | 534 // use them to distinguish frames at merge points. |
565 if (cgen_ != other->cgen_) return false; | 535 if (cgen_ != other->cgen_) return false; |
566 if (masm_ != other->masm_) return false; | 536 if (masm_ != other->masm_) return false; |
567 if (parameter_count_ != other->parameter_count_) return false; | 537 if (parameter_count_ != other->parameter_count_) return false; |
568 if (local_count_ != other->local_count_) return false; | 538 if (local_count_ != other->local_count_) return false; |
569 if (frame_pointer_ != other->frame_pointer_) return false; | 539 if (frame_pointer_ != other->frame_pointer_) return false; |
570 | 540 |
571 for (int i = 0; i < kNumRegisters; i++) { | 541 for (int i = 0; i < kNumRegisters; i++) { |
572 if (frame_registers_.count(i) != other->frame_registers_.count(i)) { | |
573 return false; | |
574 } | |
575 if (register_locations_[i] != other->register_locations_[i]) { | 542 if (register_locations_[i] != other->register_locations_[i]) { |
576 return false; | 543 return false; |
577 } | 544 } |
578 } | 545 } |
579 if (elements_.length() != other->elements_.length()) return false; | 546 if (elements_.length() != other->elements_.length()) return false; |
580 #endif | 547 #endif |
581 if (stack_pointer_ != other->stack_pointer_) return false; | 548 if (stack_pointer_ != other->stack_pointer_) return false; |
582 for (int i = 0; i < elements_.length(); i++) { | 549 for (int i = 0; i < elements_.length(); i++) { |
583 if (!elements_[i].Equals(other->elements_[i])) return false; | 550 if (!elements_[i].Equals(other->elements_[i])) return false; |
584 } | 551 } |
585 | 552 |
586 return true; | 553 return true; |
587 } | 554 } |
588 | 555 |
589 } } // namespace v8::internal | 556 } } // namespace v8::internal |
OLD | NEW |