| 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 |