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; | |
198 int best_register_code = no_reg.code_; | |
199 | |
200 for (int i = 0; i < kNumRegisters; i++) { | 188 for (int i = 0; i < kNumRegisters; i++) { |
201 int count = frame_registers_.count(i); | 189 if (is_used(i) && cgen_->allocator()->count(i) == 1) { |
202 if (count < min_count && count == cgen_->allocator()->count(i)) { | 190 Register result = { i }; |
203 min_count = count; | 191 Spill(result); |
204 best_register_code = i; | 192 ASSERT(!cgen_->allocator()->is_used(result)); |
| 193 return result; |
205 } | 194 } |
206 } | 195 } |
207 | 196 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 } | 197 } |
215 | 198 |
216 | 199 |
217 // Make the type of the element at a given index be MEMORY. | 200 // Make the type of the element at a given index be MEMORY. |
218 void VirtualFrame::SpillElementAt(int index) { | 201 void VirtualFrame::SpillElementAt(int index) { |
219 if (!elements_[index].is_valid()) return; | 202 if (!elements_[index].is_valid()) return; |
220 | 203 |
221 SyncElementAt(index); | 204 SyncElementAt(index); |
222 // The element is now in memory. Its copied flag is preserved. | 205 // The element is now in memory. Its copied flag is preserved. |
223 FrameElement new_element = FrameElement::MemoryElement(); | 206 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 | 255 // No code needs to be generated to move values to memory if |
273 // they are already synced. We perform those moves here, before | 256 // they are already synced. We perform those moves here, before |
274 // merging. | 257 // merging. |
275 if (source.is_register()) { | 258 if (source.is_register()) { |
276 // If the frame is the code generator's current frame, we have | 259 // If the frame is the code generator's current frame, we have |
277 // to decrement both the frame-internal and global register | 260 // to decrement both the frame-internal and global register |
278 // counts. | 261 // counts. |
279 if (cgen_->frame() == this) { | 262 if (cgen_->frame() == this) { |
280 Unuse(source.reg()); | 263 Unuse(source.reg()); |
281 } else { | 264 } else { |
282 frame_registers_.Unuse(source.reg()); | |
283 register_locations_[source.reg().code()] = kIllegalIndex; | 265 register_locations_[source.reg().code()] = kIllegalIndex; |
284 } | 266 } |
285 } | 267 } |
286 elements_[i] = target; | 268 elements_[i] = target; |
287 } else if (target.is_register() && !target.is_synced() && | 269 } else if (target.is_register() && !target.is_synced() && |
288 !source.is_memory()) { | 270 !source.is_memory()) { |
289 // If an element's target is a register that doesn't need to be | 271 // 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 | 272 // synced, and the element is not in memory, then the sync state |
291 // of the element is irrelevant. We clear the sync bit. | 273 // of the element is irrelevant. We clear the sync bit. |
292 ASSERT(source.is_valid()); | 274 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()); | 365 && original.handle().is_identical_to(value->handle()); |
384 if (same_register || same_constant) { | 366 if (same_register || same_constant) { |
385 value->Unuse(); | 367 value->Unuse(); |
386 return; | 368 return; |
387 } | 369 } |
388 | 370 |
389 InvalidateFrameSlotAt(frame_index); | 371 InvalidateFrameSlotAt(frame_index); |
390 | 372 |
391 FrameElement new_element; | 373 FrameElement new_element; |
392 if (value->is_register()) { | 374 if (value->is_register()) { |
393 // There are two cases depending no whether the register already | 375 if (is_used(value->reg())) { |
394 // occurs in the frame or not. | 376 // The register already appears on the frame. Either the existing |
395 if (register_count(value->reg()) == 0) { | 377 // register element, or the new element at frame_index, must be made |
396 Use(value->reg(), frame_index); | 378 // a copy. |
397 elements_[frame_index] = | 379 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) { | 380 if (i < frame_index) { |
410 // The register backing store is lower in the frame than its copy. | 381 // The register FrameElement is lower in the frame than the new copy. |
411 elements_[frame_index] = CopyElementAt(i); | 382 elements_[frame_index] = CopyElementAt(i); |
412 } else { | 383 } else { |
413 // There was an early bailout for the case of setting a | 384 // There was an early bailout for the case of setting a |
414 // register element to itself. | 385 // register element to itself. |
415 ASSERT(i != frame_index); | 386 ASSERT(i != frame_index); |
416 elements_[frame_index] = elements_[i]; | 387 elements_[frame_index] = elements_[i]; |
417 elements_[i] = CopyElementAt(frame_index); | 388 elements_[i] = CopyElementAt(frame_index); |
418 if (elements_[frame_index].is_synced()) { | 389 if (elements_[frame_index].is_synced()) { |
419 elements_[i].set_sync(); | 390 elements_[i].set_sync(); |
420 } | 391 } |
421 elements_[frame_index].clear_sync(); | 392 elements_[frame_index].clear_sync(); |
422 register_locations_[value->reg().code()] = frame_index; | 393 register_locations_[value->reg().code()] = frame_index; |
423 for (int j = i + 1; j < elements_.length(); j++) { | 394 for (int j = i + 1; j < elements_.length(); j++) { |
424 if (elements_[j].is_copy() && elements_[j].index() == i) { | 395 if (elements_[j].is_copy() && elements_[j].index() == i) { |
425 elements_[j].set_index(frame_index); | 396 elements_[j].set_index(frame_index); |
426 } | 397 } |
427 } | 398 } |
428 } | 399 } |
| 400 } else { |
| 401 // The register value->reg() was not already used on the frame. |
| 402 Use(value->reg(), frame_index); |
| 403 elements_[frame_index] = |
| 404 FrameElement::RegisterElement(value->reg(), |
| 405 FrameElement::NOT_SYNCED); |
429 } | 406 } |
430 } else { | 407 } else { |
431 ASSERT(value->is_constant()); | 408 ASSERT(value->is_constant()); |
432 elements_[frame_index] = | 409 elements_[frame_index] = |
433 FrameElement::ConstantElement(value->handle(), | 410 FrameElement::ConstantElement(value->handle(), |
434 FrameElement::NOT_SYNCED); | 411 FrameElement::NOT_SYNCED); |
435 } | 412 } |
436 value->Unuse(); | 413 value->Unuse(); |
437 } | 414 } |
438 | 415 |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
490 // a different signature. | 467 // a different signature. |
491 UNREACHABLE(); | 468 UNREACHABLE(); |
492 break; | 469 break; |
493 } | 470 } |
494 PrepareForCall(spilled_args, dropped_args); | 471 PrepareForCall(spilled_args, dropped_args); |
495 return RawCallCodeObject(code, rmode); | 472 return RawCallCodeObject(code, rmode); |
496 } | 473 } |
497 | 474 |
498 | 475 |
499 void VirtualFrame::Push(Register reg) { | 476 void VirtualFrame::Push(Register reg) { |
500 FrameElement new_element; | 477 if (is_used(reg)) { |
501 if (register_count(reg) == 0) { | 478 elements_.Add(CopyElementAt(register_index(reg))); |
| 479 } else { |
502 Use(reg, elements_.length()); | 480 Use(reg, elements_.length()); |
503 new_element = | 481 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 } | 482 } |
514 elements_.Add(new_element); | |
515 } | 483 } |
516 | 484 |
517 | 485 |
518 void VirtualFrame::Push(Handle<Object> value) { | 486 void VirtualFrame::Push(Handle<Object> value) { |
519 elements_.Add(FrameElement::ConstantElement(value, | 487 elements_.Add(FrameElement::ConstantElement(value, |
520 FrameElement::NOT_SYNCED)); | 488 FrameElement::NOT_SYNCED)); |
521 } | 489 } |
522 | 490 |
523 | 491 |
524 void VirtualFrame::Push(Result* result) { | 492 void VirtualFrame::Push(Result* result) { |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
562 #ifdef DEBUG | 530 #ifdef DEBUG |
563 // These are sanity checks in debug builds, but we do not need to | 531 // These are sanity checks in debug builds, but we do not need to |
564 // use them to distinguish frames at merge points. | 532 // use them to distinguish frames at merge points. |
565 if (cgen_ != other->cgen_) return false; | 533 if (cgen_ != other->cgen_) return false; |
566 if (masm_ != other->masm_) return false; | 534 if (masm_ != other->masm_) return false; |
567 if (parameter_count_ != other->parameter_count_) return false; | 535 if (parameter_count_ != other->parameter_count_) return false; |
568 if (local_count_ != other->local_count_) return false; | 536 if (local_count_ != other->local_count_) return false; |
569 if (frame_pointer_ != other->frame_pointer_) return false; | 537 if (frame_pointer_ != other->frame_pointer_) return false; |
570 | 538 |
571 for (int i = 0; i < kNumRegisters; i++) { | 539 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]) { | 540 if (register_locations_[i] != other->register_locations_[i]) { |
576 return false; | 541 return false; |
577 } | 542 } |
578 } | 543 } |
579 if (elements_.length() != other->elements_.length()) return false; | 544 if (elements_.length() != other->elements_.length()) return false; |
580 #endif | 545 #endif |
581 if (stack_pointer_ != other->stack_pointer_) return false; | 546 if (stack_pointer_ != other->stack_pointer_) return false; |
582 for (int i = 0; i < elements_.length(); i++) { | 547 for (int i = 0; i < elements_.length(); i++) { |
583 if (!elements_[i].Equals(other->elements_[i])) return false; | 548 if (!elements_[i].Equals(other->elements_[i])) return false; |
584 } | 549 } |
585 | 550 |
586 return true; | 551 return true; |
587 } | 552 } |
588 | 553 |
589 } } // namespace v8::internal | 554 } } // namespace v8::internal |
OLD | NEW |