OLD | NEW |
1 // Copyright 2008 the V8 project authors. All rights reserved. | 1 // Copyright 2008 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 480 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
491 | 491 |
492 | 492 |
493 void VirtualFrame::PushReceiverSlotAddress() { | 493 void VirtualFrame::PushReceiverSlotAddress() { |
494 Result temp = cgen_->allocator()->Allocate(); | 494 Result temp = cgen_->allocator()->Allocate(); |
495 ASSERT(temp.is_valid()); | 495 ASSERT(temp.is_valid()); |
496 __ lea(temp.reg(), ParameterAt(-1)); | 496 __ lea(temp.reg(), ParameterAt(-1)); |
497 Push(&temp); | 497 Push(&temp); |
498 } | 498 } |
499 | 499 |
500 | 500 |
501 // Before changing an element which is copied, adjust so that the | 501 int VirtualFrame::InvalidateFrameSlotAt(int index) { |
502 // first copy becomes the new backing store and all the other copies | |
503 // are updated. If the original was in memory, the new backing store | |
504 // is allocated to a register. Return a copy of the new backing store | |
505 // or an invalid element if the original was not a copy. | |
506 FrameElement VirtualFrame::AdjustCopies(int index) { | |
507 FrameElement original = elements_[index]; | 502 FrameElement original = elements_[index]; |
508 ASSERT(original.is_memory() || original.is_register()); | |
509 | 503 |
510 // Go looking for a first copy above index. | 504 // Is this element the backing store of any copies? |
511 int i = index + 1; | 505 int new_backing_index = kIllegalIndex; |
512 while (i < elements_.length()) { | 506 if (original.is_copied()) { |
513 FrameElement elt = elements_[i]; | 507 // Verify it is copied, and find first copy. |
514 if (elt.is_copy() && elt.index() == index) break; | 508 for (int i = index + 1; i < elements_.length(); i++) { |
515 i++; | 509 if (elements_[i].is_copy() && elements_[i].index() == index) { |
| 510 new_backing_index = i; |
| 511 break; |
| 512 } |
| 513 } |
516 } | 514 } |
517 | 515 |
518 if (i < elements_.length()) { | 516 if (new_backing_index == kIllegalIndex) { |
519 // There was a first copy. Make it the new backing element. | 517 // No copies found, return kIllegalIndex. |
520 Register backing_reg; | 518 if (original.is_register()) { |
521 if (original.is_memory()) { | 519 Unuse(original.reg()); |
522 Result fresh = cgen_->allocator()->Allocate(); | |
523 ASSERT(fresh.is_valid()); | |
524 backing_reg = fresh.reg(); | |
525 __ mov(backing_reg, Operand(ebp, fp_relative(index))); | |
526 } else { | |
527 // The original was in a register. | |
528 backing_reg = original.reg(); | |
529 } | 520 } |
530 FrameElement new_backing_element = | 521 elements_[index] = FrameElement::InvalidElement(); |
531 FrameElement::RegisterElement(backing_reg, FrameElement::NOT_SYNCED); | 522 return kIllegalIndex; |
532 if (elements_[i].is_synced()) { | |
533 new_backing_element.set_sync(); | |
534 } | |
535 Use(backing_reg); | |
536 elements_[i] = new_backing_element; | |
537 | |
538 // Update the other copies. | |
539 FrameElement copy = CopyElementAt(i); | |
540 for (int j = i; j < elements_.length(); j++) { | |
541 FrameElement elt = elements_[j]; | |
542 if (elt.is_copy() && elt.index() == index) { | |
543 if (elt.is_synced()) { | |
544 copy.set_sync(); | |
545 } else { | |
546 copy.clear_sync(); | |
547 } | |
548 elements_[j] = copy; | |
549 } | |
550 } | |
551 | |
552 copy.clear_sync(); | |
553 return copy; | |
554 } | 523 } |
555 | 524 |
556 elements_[index].clear_copied(); | 525 // This is the backing store of copies. |
557 return FrameElement::InvalidElement(); | 526 Register backing_reg; |
| 527 if (original.is_memory()) { |
| 528 Result fresh = cgen_->allocator()->Allocate(); |
| 529 ASSERT(fresh.is_valid()); |
| 530 Use(fresh.reg()); |
| 531 backing_reg = fresh.reg(); |
| 532 __ mov(backing_reg, Operand(ebp, fp_relative(index))); |
| 533 } else { |
| 534 // The original was in a register. |
| 535 backing_reg = original.reg(); |
| 536 } |
| 537 if (elements_[new_backing_index].is_synced()) { |
| 538 elements_[new_backing_index] = |
| 539 FrameElement::RegisterElement(backing_reg, FrameElement::SYNCED); |
| 540 } else { |
| 541 elements_[new_backing_index] = |
| 542 FrameElement::RegisterElement(backing_reg, FrameElement::NOT_SYNCED); |
| 543 } |
| 544 // Update the other copies. |
| 545 for (int i = new_backing_index + 1; i < elements_.length(); i++) { |
| 546 if (elements_[i].is_copy() && elements_[i].index() == index) { |
| 547 elements_[i].set_index(new_backing_index); |
| 548 elements_[new_backing_index].set_copied(); |
| 549 } |
| 550 } |
| 551 return new_backing_index; |
558 } | 552 } |
559 | 553 |
560 | 554 |
561 void VirtualFrame::TakeFrameSlotAt(int index) { | 555 void VirtualFrame::TakeFrameSlotAt(int index) { |
562 ASSERT(index >= 0); | 556 ASSERT(index >= 0); |
563 ASSERT(index <= elements_.length()); | 557 ASSERT(index <= elements_.length()); |
564 FrameElement original = elements_[index]; | 558 FrameElement original = elements_[index]; |
| 559 int new_backing_store_index = InvalidateFrameSlotAt(index); |
| 560 if (new_backing_store_index != kIllegalIndex) { |
| 561 elements_.Add(CopyElementAt(new_backing_store_index)); |
| 562 return; |
| 563 } |
565 | 564 |
566 switch (original.type()) { | 565 switch (original.type()) { |
567 case FrameElement::INVALID: | |
568 UNREACHABLE(); | |
569 break; | |
570 | |
571 case FrameElement::MEMORY: { | 566 case FrameElement::MEMORY: { |
572 // Allocate the element to a register. If it is not copied, | 567 // Emit code to load the original element's data into a register. |
573 // push that register on top of the frame. If it is copied, | 568 // Push that register as a FrameElement on top of the frame. |
574 // make the first copy the backing store and push a fresh copy | 569 Result fresh = cgen_->allocator()->Allocate(); |
575 // on top of the frame. | 570 ASSERT(fresh.is_valid()); |
576 FrameElement copy = original.is_copied() | 571 FrameElement new_element = |
577 ? AdjustCopies(index) | 572 FrameElement::RegisterElement(fresh.reg(), |
578 : FrameElement::InvalidElement(); | 573 FrameElement::NOT_SYNCED); |
579 if (copy.is_valid()) { | 574 Use(fresh.reg()); |
580 // The original element was a copy. Push the copy of the new | 575 elements_.Add(new_element); |
581 // backing store. | 576 __ mov(fresh.reg(), Operand(ebp, fp_relative(index))); |
582 elements_.Add(copy); | |
583 } else { | |
584 // The element was not a copy. Move it to a register and push | |
585 // that. | |
586 Result fresh = cgen_->allocator()->Allocate(); | |
587 ASSERT(fresh.is_valid()); | |
588 FrameElement new_element = | |
589 FrameElement::RegisterElement(fresh.reg(), | |
590 FrameElement::NOT_SYNCED); | |
591 Use(fresh.reg()); | |
592 elements_.Add(new_element); | |
593 __ mov(fresh.reg(), Operand(ebp, fp_relative(index))); | |
594 } | |
595 break; | 577 break; |
596 } | 578 } |
597 | 579 case FrameElement::REGISTER: |
598 case FrameElement::REGISTER: { | 580 Use(original.reg()); |
599 // If the element is not copied, push it on top of the frame. | 581 // Fall through. |
600 // If it is copied, make the first copy be the new backing store | |
601 // and push a fresh copy on top of the frame. | |
602 FrameElement copy = original.is_copied() | |
603 ? AdjustCopies(index) | |
604 : FrameElement::InvalidElement(); | |
605 if (copy.is_valid()) { | |
606 // The original element was a copy. Push the copy of the new | |
607 // backing store. | |
608 elements_.Add(copy); | |
609 // This is the only case where we have to unuse the original | |
610 // register. The original is still counted and so is the new | |
611 // backing store of the copies. | |
612 Unuse(original.reg()); | |
613 } else { | |
614 // The element was not a copy. Push it. | |
615 original.clear_sync(); | |
616 elements_.Add(original); | |
617 } | |
618 break; | |
619 } | |
620 | |
621 case FrameElement::CONSTANT: | 582 case FrameElement::CONSTANT: |
622 original.clear_sync(); | |
623 elements_.Add(original); | |
624 break; | |
625 | |
626 case FrameElement::COPY: | 583 case FrameElement::COPY: |
627 original.clear_sync(); | 584 original.clear_sync(); |
628 elements_.Add(original); | 585 elements_.Add(original); |
629 break; | 586 break; |
| 587 case FrameElement::INVALID: |
| 588 UNREACHABLE(); |
| 589 break; |
630 } | 590 } |
631 elements_[index] = FrameElement::InvalidElement(); | |
632 } | 591 } |
633 | 592 |
634 | 593 |
635 void VirtualFrame::StoreToFrameSlotAt(int index) { | 594 void VirtualFrame::StoreToFrameSlotAt(int index) { |
636 // Store the value on top of the frame to the virtual frame slot at | 595 // Store the value on top of the frame to the virtual frame slot at |
637 // a given index. The value on top of the frame is left in place. | 596 // a given index. The value on top of the frame is left in place. |
638 // This is a duplicating operation, so it can create copies. | 597 // This is a duplicating operation, so it can create copies. |
639 ASSERT(index >= 0); | 598 ASSERT(index >= 0); |
640 ASSERT(index < elements_.length()); | 599 ASSERT(index < elements_.length()); |
641 | 600 |
642 FrameElement original = elements_[index]; | |
643 // If the stored-to slot may be copied, adjust to preserve the | |
644 // copy-on-write semantics of copied elements. | |
645 if (original.is_copied() && | |
646 (original.is_register() || original.is_memory())) { | |
647 FrameElement ignored = AdjustCopies(index); | |
648 } | |
649 | |
650 // If the stored-to slot is a register reference, deallocate it. | |
651 if (original.is_register()) { | |
652 Unuse(original.reg()); | |
653 } | |
654 | |
655 int top_index = elements_.length() - 1; | 601 int top_index = elements_.length() - 1; |
656 FrameElement top = elements_[top_index]; | 602 FrameElement top = elements_[top_index]; |
| 603 FrameElement original = elements_[index]; |
| 604 if (top.is_copy() && top.index() == index) return; |
657 ASSERT(top.is_valid()); | 605 ASSERT(top.is_valid()); |
658 | 606 |
| 607 InvalidateFrameSlotAt(index); |
| 608 |
659 if (top.is_copy()) { | 609 if (top.is_copy()) { |
660 // There are two cases based on the relative positions of the | 610 // There are two cases based on the relative positions of the |
661 // stored-to slot and the backing slot of the top element. | 611 // stored-to slot and the backing slot of the top element. |
662 int backing_index = top.index(); | 612 int backing_index = top.index(); |
663 ASSERT(backing_index != index); | 613 ASSERT(backing_index != index); |
664 if (backing_index < index) { | 614 if (backing_index < index) { |
665 // 1. The top element is a copy of a slot below the stored-to | 615 // 1. The top element is a copy of a slot below the stored-to |
666 // slot. The stored-to slot becomes an unsynced copy of that | 616 // slot. The stored-to slot becomes an unsynced copy of that |
667 // same backing slot. | 617 // same backing slot. |
668 elements_[index] = CopyElementAt(backing_index); | 618 elements_[index] = CopyElementAt(backing_index); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
700 // element. | 650 // element. |
701 FrameElement new_element = CopyElementAt(index); | 651 FrameElement new_element = CopyElementAt(index); |
702 elements_[backing_index] = new_element; | 652 elements_[backing_index] = new_element; |
703 if (backing_element.is_synced()) { | 653 if (backing_element.is_synced()) { |
704 elements_[backing_index].set_sync(); | 654 elements_[backing_index].set_sync(); |
705 } | 655 } |
706 | 656 |
707 // All the copies of the old backing element (including the top | 657 // All the copies of the old backing element (including the top |
708 // element) become copies of the new backing element. | 658 // element) become copies of the new backing element. |
709 for (int i = backing_index + 1; i < elements_.length(); i++) { | 659 for (int i = backing_index + 1; i < elements_.length(); i++) { |
710 FrameElement current = elements_[i]; | 660 if (elements_[i].is_copy() && elements_[i].index() == backing_index) { |
711 if (current.is_copy() && current.index() == backing_index) { | 661 elements_[i].set_index(index); |
712 elements_[i] = new_element; | |
713 if (current.is_synced()) { | |
714 elements_[i].set_sync(); | |
715 } | |
716 } | 662 } |
717 } | 663 } |
718 } | 664 } |
719 | |
720 return; | 665 return; |
721 } | 666 } |
722 | 667 |
723 // Move the top element to the stored-to slot and replace it (the | 668 // Move the top element to the stored-to slot and replace it (the |
724 // top element) with a copy. | 669 // top element) with a copy. |
725 elements_[index] = top; | 670 elements_[index] = top; |
726 if (top.is_memory()) { | 671 if (top.is_memory()) { |
727 // TODO(209): consider allocating the stored-to slot to the temp | 672 // TODO(209): consider allocating the stored-to slot to the temp |
728 // register. Alternatively, allow copies to appear in any order | 673 // register. Alternatively, allow copies to appear in any order |
729 // in the frame and lazily move the value down to the slot. | 674 // in the frame and lazily move the value down to the slot. |
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
995 ASSERT(stack_pointer_ == elements_.length() - 1); | 940 ASSERT(stack_pointer_ == elements_.length() - 1); |
996 elements_.Add(FrameElement::MemoryElement()); | 941 elements_.Add(FrameElement::MemoryElement()); |
997 stack_pointer_++; | 942 stack_pointer_++; |
998 __ push(immediate); | 943 __ push(immediate); |
999 } | 944 } |
1000 | 945 |
1001 | 946 |
1002 #undef __ | 947 #undef __ |
1003 | 948 |
1004 } } // namespace v8::internal | 949 } } // namespace v8::internal |
OLD | NEW |