Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2)

Side by Side Diff: src/virtual-frame-ia32.cc

Issue 20257: Experimental: when doing memory-to-memory moves as part of a frame... (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/toiger/
Patch Set: Created 11 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/virtual-frame-ia32.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 523 matching lines...) Expand 10 before | Expand all | Expand 10 after
534 ASSERT(cgen_->HasValidEntryRegisters()); 534 ASSERT(cgen_->HasValidEntryRegisters());
535 } 535 }
536 536
537 537
538 void VirtualFrame::MergeTo(VirtualFrame* expected) { 538 void VirtualFrame::MergeTo(VirtualFrame* expected) {
539 Comment cmnt(masm_, "[ Merge frame"); 539 Comment cmnt(masm_, "[ Merge frame");
540 // We should always be merging the code generator's current frame to an 540 // We should always be merging the code generator's current frame to an
541 // expected frame. 541 // expected frame.
542 ASSERT(cgen_->frame() == this); 542 ASSERT(cgen_->frame() == this);
543 543
544 ASSERT(cgen_ == expected->cgen_);
545 ASSERT(masm_ == expected->masm_);
546 ASSERT(elements_.length() == expected->elements_.length());
547 ASSERT(parameter_count_ == expected->parameter_count_);
548 ASSERT(local_count_ == expected->local_count_);
549 ASSERT(frame_pointer_ == expected->frame_pointer_);
550
551 // Mergable frames have all elements in locations, either memory or
552 // register. We thus have a series of to-memory and to-register moves.
553 // First perform all to-memory moves, register-to-memory moves because
554 // they can free registers and constant-to-memory moves because they do
555 // not use registers.
556 MergeMoveRegistersToMemory(expected); 544 MergeMoveRegistersToMemory(expected);
557 MergeMoveRegistersToRegisters(expected); 545 MergeMoveRegistersToRegisters(expected);
558 MergeMoveMemoryToRegisters(expected); 546 MergeMoveMemoryToRegisters(expected);
559 547
560 int height_difference = stack_pointer_ - expected->stack_pointer_; 548 int height_difference = stack_pointer_ - expected->stack_pointer_;
561 if (stack_pointer_ > expected->stack_pointer_) { 549 if (stack_pointer_ > expected->stack_pointer_) {
562 #ifdef DEBUG 550 #ifdef DEBUG
563 for (int i = stack_pointer_; i > expected->stack_pointer_; i--) { 551 for (int i = stack_pointer_; i > expected->stack_pointer_; i--) {
564 ASSERT(!elements_[i].is_memory()); 552 ASSERT(!elements_[i].is_memory());
565 ASSERT(!elements_[i].is_synced()); 553 ASSERT(!elements_[i].is_synced());
566 } 554 }
567 #endif 555 #endif
568 __ add(Operand(esp), Immediate(height_difference * kPointerSize)); 556 __ add(Operand(esp), Immediate(height_difference * kPointerSize));
569 stack_pointer_ = expected->stack_pointer_; 557 stack_pointer_ = expected->stack_pointer_;
570 } else if (stack_pointer_ < expected->stack_pointer_) { 558 } else if (stack_pointer_ < expected->stack_pointer_) {
571 // Put valid data on the stack, that will only be accessed by GC. 559 // Put valid data on the stack, that will only be accessed by GC.
572 while (stack_pointer_ < expected->stack_pointer_) { 560 while (stack_pointer_ < expected->stack_pointer_) {
573 __ push(Immediate(Smi::FromInt(0))); 561 __ push(Immediate(Smi::FromInt(0)));
574 stack_pointer_++; 562 stack_pointer_++;
575 } 563 }
576 } 564 }
577 565
578 // At this point, the frames should be identical. 566 // At this point, the frames should be identical.
579 // TODO(208): Consider an "equals" method for frames. 567 ASSERT(Equals(expected));
580 ASSERT(stack_pointer_ == expected->stack_pointer_);
581 #ifdef DEBUG
582 for (int i = 0; i < elements_.length(); i++) {
583 FrameElement expect = expected->elements_[i];
584 if (!expect.is_valid()) {
585 ASSERT(!elements_[i].is_valid());
586 } else if (expect.is_memory()) {
587 ASSERT(elements_[i].is_memory());
588 ASSERT(elements_[i].is_synced() && expect.is_synced());
589 } else if (expect.is_register()) {
590 ASSERT(elements_[i].is_register());
591 ASSERT(elements_[i].reg().is(expect.reg()));
592 ASSERT(elements_[i].is_synced() == expect.is_synced());
593 } else {
594 ASSERT(expect.is_constant());
595 ASSERT(elements_[i].is_constant());
596 ASSERT(elements_[i].handle().location() ==
597 expect.handle().location());
598 ASSERT(elements_[i].is_synced() == expect.is_synced());
599 }
600 }
601 #endif
602 } 568 }
603 569
604 570
605 void VirtualFrame::MergeMoveRegistersToMemory(VirtualFrame *expected) { 571 void VirtualFrame::MergeMoveRegistersToMemory(VirtualFrame* expected) {
606 // Move registers, constants, and copies to memory. 572 // Adjust the stack pointer upward (toward the top of the virtual
607 for (int i = 0; i < elements_.length(); i++) { 573 // frame) if necessary.
608 FrameElement source = elements_[i]; 574 if (stack_pointer_ < expected->stack_pointer_) {
575 int difference = expected->stack_pointer_ - stack_pointer_;
576 stack_pointer_ = expected->stack_pointer_;
577 __ sub(Operand(esp), Immediate(difference * kPointerSize));
578 }
579 ASSERT(stack_pointer_ >= expected->stack_pointer_);
580
581 // Move registers, constants, and copies to memory. Perform moves
582 // from the top downward in the frame in order to leave the backing
583 // stores of copies in registers.
584 //
585 // Moving memory-backed copies to memory requires a spare register
586 // for the memory-to-memory moves. Since we are performing a merge,
587 // we use esi (which is already saved in the frame). We keep track
588 // of the index of the frame element esi is caching or kIllegalIndex
589 // if esi has not been disturbed.
590 int esi_caches = kIllegalIndex;
591 // A "singleton" memory element.
592 FrameElement memory_element = FrameElement::MemoryElement();
593 for (int i = stack_pointer_; i >= 0; i--) {
609 FrameElement target = expected->elements_[i]; 594 FrameElement target = expected->elements_[i];
610 if (target.is_memory() && !source.is_memory()) { 595 if (target.is_memory()) {
611 ASSERT(source.is_register() || 596 FrameElement source = elements_[i];
612 source.is_constant() || 597 switch (source.type()) {
613 source.is_copy()); 598 case FrameElement::INVALID:
614 SpillElementAt(i); 599 // Not a legal merge move.
600 UNREACHABLE();
601 break;
602
603 case FrameElement::MEMORY:
604 // Already in place.
605 break;
606
607 case FrameElement::REGISTER:
608 Unuse(source.reg());
609 if (!source.is_synced()) {
610 __ mov(Operand(ebp, fp_relative(i)), source.reg());
611 }
612 break;
613
614 case FrameElement::CONSTANT:
615 if (!source.is_synced()) {
616 __ Set(Operand(ebp, fp_relative(i)), Immediate(source.handle()));
617 }
618 break;
619
620 case FrameElement::COPY:
621 if (!source.is_synced()) {
622 int backing_index = source.index();
623 FrameElement backing_element = elements_[backing_index];
624 if (backing_element.is_memory()) {
625 // If we have to spill a register, we spill esi.
626 if (esi_caches != backing_index) {
627 esi_caches = backing_index;
628 __ mov(esi, Operand(ebp, fp_relative(backing_index)));
629 }
630 __ mov(Operand(ebp, fp_relative(i)), esi);
631 } else {
632 ASSERT(backing_element.is_register());
633 __ mov(Operand(ebp, fp_relative(i)), backing_element.reg());
634 }
635 }
636 break;
637 }
638 elements_[i] = memory_element;
615 } 639 }
616 } 640 }
641
642 if (esi_caches != kIllegalIndex) {
643 __ mov(esi, Operand(ebp, fp_relative(context_index())));
644 }
617 } 645 }
618 646
619 647
620 void VirtualFrame::MergeMoveRegistersToRegisters(VirtualFrame *expected) { 648 void VirtualFrame::MergeMoveRegistersToRegisters(VirtualFrame* expected) {
649 // We have already done X-to-memory moves.
650 ASSERT(stack_pointer_ >= expected->stack_pointer_);
651
621 // Perform register-to-register moves. 652 // Perform register-to-register moves.
622 int start = 0; 653 int start = 0;
623 int end = elements_.length() - 1; 654 int end = elements_.length() - 1;
624 bool any_moves_blocked; // Did we fail to make some moves this iteration? 655 bool any_moves_blocked; // Did we fail to make some moves this iteration?
625 bool should_break_cycles = false; 656 bool should_break_cycles = false;
626 bool any_moves_made; // Did we make any progress this iteration? 657 bool any_moves_made; // Did we make any progress this iteration?
627 do { 658 do {
628 any_moves_blocked = false; 659 any_moves_blocked = false;
629 any_moves_made = false; 660 any_moves_made = false;
630 int first_move_blocked = kIllegalIndex; 661 int first_move_blocked = kIllegalIndex;
631 int last_move_blocked = kIllegalIndex; 662 int last_move_blocked = kIllegalIndex;
632 for (int i = start; i <= end; i++) { 663 for (int i = start; i <= end; i++) {
633 FrameElement source = elements_[i]; 664 FrameElement source = elements_[i];
634 FrameElement target = expected->elements_[i]; 665 FrameElement target = expected->elements_[i];
635 if (source.is_register() && target.is_register()) { 666 if (source.is_register() && target.is_register()) {
William Hesse 2009/02/11 09:46:47 What is the precondition on the frame and expected
636 if (target.reg().is(source.reg())) { 667 if (target.reg().is(source.reg())) {
637 if (target.is_synced() && !source.is_synced()) { 668 if (target.is_synced() && !source.is_synced()) {
638 SyncElementAt(i); 669 __ mov(Operand(ebp, fp_relative(i)), source.reg());
639 } 670 }
640 elements_[i] = target; 671 elements_[i] = target;
641 } else { 672 } else {
642 // We need to move source to target. 673 // We need to move source to target.
643 if (frame_registers_.is_used(target.reg())) { 674 if (frame_registers_.is_used(target.reg())) {
644 // The move is blocked because the target contains valid data. 675 // The move is blocked because the target contains valid data.
645 // If we are stuck with only cycles remaining, then we spill source. 676 // If we are stuck with only cycles remaining, then we spill source.
646 // Otherwise, we just need more iterations. 677 // Otherwise, we just need more iterations.
647 if (should_break_cycles) { 678 if (should_break_cycles) {
648 SpillElementAt(i); 679 SpillElementAt(i);
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
753 void VirtualFrame::Enter() { 784 void VirtualFrame::Enter() {
754 // Registers live on entry: esp, ebp, esi, edi. 785 // Registers live on entry: esp, ebp, esi, edi.
755 Comment cmnt(masm_, "[ Enter JS frame"); 786 Comment cmnt(masm_, "[ Enter JS frame");
756 EmitPush(ebp); 787 EmitPush(ebp);
757 788
758 frame_pointer_ = stack_pointer_; 789 frame_pointer_ = stack_pointer_;
759 __ mov(ebp, Operand(esp)); 790 __ mov(ebp, Operand(esp));
760 791
761 // Store the context in the frame. The context is kept in esi and a 792 // Store the context in the frame. The context is kept in esi and a
762 // copy is stored in the frame. The external reference to esi 793 // copy is stored in the frame. The external reference to esi
763 // remains in addition to the cached copy in the frame. 794 // remains.
764 Push(esi); 795 EmitPush(esi);
William Hesse 2009/02/11 09:46:47 I didn't know we were keeping EmitPush(). Which o
765 SyncElementAt(elements_.length() - 1);
766 796
767 // Store the function in the frame. The frame owns the register 797 // Store the function in the frame. The frame owns the register
768 // reference now (ie, it can keep it in edi or spill it later). 798 // reference now (ie, it can keep it in edi or spill it later).
769 Push(edi); 799 Push(edi);
800 SyncElementAt(elements_.length() - 1);
770 cgen_->allocator()->Unuse(edi); 801 cgen_->allocator()->Unuse(edi);
771 SpillElementAt(elements_.length() - 1);
772 } 802 }
773 803
774 804
775 void VirtualFrame::Exit() { 805 void VirtualFrame::Exit() {
776 Comment cmnt(masm_, "[ Exit JS frame"); 806 Comment cmnt(masm_, "[ Exit JS frame");
777 // Record the location of the JS exit code for patching when setting 807 // Record the location of the JS exit code for patching when setting
778 // break point. 808 // break point.
779 __ RecordJSReturn(); 809 __ RecordJSReturn();
780 810
781 // Avoid using the leave instruction here, because it is too 811 // Avoid using the leave instruction here, because it is too
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
901 ASSERT(value->is_constant()); 931 ASSERT(value->is_constant());
902 elements_[frame_index] = 932 elements_[frame_index] =
903 FrameElement::ConstantElement(value->handle(), 933 FrameElement::ConstantElement(value->handle(),
904 FrameElement::NOT_SYNCED); 934 FrameElement::NOT_SYNCED);
905 } 935 }
906 value->Unuse(); 936 value->Unuse();
907 } 937 }
908 938
909 939
910 void VirtualFrame::SaveContextRegister() { 940 void VirtualFrame::SaveContextRegister() {
911 FrameElement current = elements_[context_index()]; 941 ASSERT(elements_[context_index()].is_memory());
912 ASSERT(current.is_register() || current.is_memory()); 942 __ mov(Operand(ebp, fp_relative(context_index())), esi);
913 if (!current.is_register() || !current.reg().is(esi)) {
914 if (current.is_register()) {
915 Unuse(current.reg());
916 }
917 Use(esi);
918 elements_[context_index()] =
919 FrameElement::RegisterElement(esi, FrameElement::NOT_SYNCED);
920 }
921 } 943 }
922 944
923 945
924 void VirtualFrame::RestoreContextRegister() { 946 void VirtualFrame::RestoreContextRegister() {
925 FrameElement current = elements_[context_index()]; 947 ASSERT(elements_[context_index()].is_memory());
926 ASSERT(current.is_register() || current.is_memory()); 948 __ mov(esi, Operand(ebp, fp_relative(context_index())));
927 if (current.is_register() && !current.reg().is(esi)) {
928 Unuse(current.reg());
929 Use(esi);
930 __ mov(esi, current.reg());
931 elements_[context_index()] =
932 FrameElement::RegisterElement(esi, FrameElement::NOT_SYNCED);
933 } else if (current.is_memory()) {
934 Use(esi);
935 __ mov(esi, Operand(ebp, fp_relative(context_index())));
936 elements_[context_index()] =
937 FrameElement::RegisterElement(esi, FrameElement::SYNCED);
938 }
939 } 949 }
940 950
941 951
942 void VirtualFrame::PushReceiverSlotAddress() { 952 void VirtualFrame::PushReceiverSlotAddress() {
943 Result temp = cgen_->allocator()->Allocate(); 953 Result temp = cgen_->allocator()->Allocate();
944 ASSERT(temp.is_valid()); 954 ASSERT(temp.is_valid());
945 __ lea(temp.reg(), ParameterAt(-1)); 955 __ lea(temp.reg(), ParameterAt(-1));
946 Push(&temp); 956 Push(&temp);
947 } 957 }
948 958
(...skipping 591 matching lines...) Expand 10 before | Expand all | Expand 10 after
1540 if (num_dropped == 0) return; 1550 if (num_dropped == 0) return;
1541 Result tos = Pop(); 1551 Result tos = Pop();
1542 if (num_dropped > 1) { 1552 if (num_dropped > 1) {
1543 Drop(num_dropped - 1); 1553 Drop(num_dropped - 1);
1544 } 1554 }
1545 SetElementAt(0, &tos); 1555 SetElementAt(0, &tos);
1546 } 1556 }
1547 1557
1548 1558
1549 #ifdef DEBUG 1559 #ifdef DEBUG
1550 bool VirtualFrame::IsSpilled() { 1560 bool FrameElement::Equals(FrameElement other) {
1561 if (type() != other.type()) return false;
1562 if (is_synced() != other.is_synced()) return false;
1563
1564 if (is_register()) {
1565 if (!reg().is(other.reg())) return false;
1566 } else if (is_constant()) {
1567 if (!handle().is_identical_to(other.handle())) return false;
1568 } else if (is_copy()) {
1569 if (index() != other.index()) return false;
1570 }
1571
1572 return true;
1573 }
1574
1575
1576 bool VirtualFrame::Equals(VirtualFrame* other) {
1577 if (cgen_ != other->cgen_) return false;
1578 if (masm_ != other->masm_) return false;
1579 if (elements_.length() != other->elements_.length()) return false;
1580
1551 for (int i = 0; i < elements_.length(); i++) { 1581 for (int i = 0; i < elements_.length(); i++) {
1552 if (!elements_[i].is_memory()) { 1582 if (!elements_[i].Equals(other->elements_[i])) return false;
1583 }
1584
1585 if (parameter_count_ != other->parameter_count_) return false;
1586 if (local_count_ != other->local_count_) return false;
1587 if (stack_pointer_ != other->stack_pointer_) return false;
1588 if (frame_pointer_ != other->frame_pointer_) return false;
1589
1590 for (int i = 0; i < RegisterFile::kNumRegisters; i++) {
1591 if (frame_registers_.count(i) != other->frame_registers_.count(i)) {
1553 return false; 1592 return false;
1554 } 1593 }
1555 } 1594 }
1595
1556 return true; 1596 return true;
1557 } 1597 }
1558 #endif 1598 #endif
1559 1599
1560 #undef __ 1600 #undef __
1561 1601
1562 } } // namespace v8::internal 1602 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/virtual-frame-ia32.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698