| 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 254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 265 SyncElementAt(i); | 265 SyncElementAt(i); |
| 266 } | 266 } |
| 267 } | 267 } |
| 268 | 268 |
| 269 // Forget the frame elements that will be popped by the call. | 269 // Forget the frame elements that will be popped by the call. |
| 270 Forget(frame_arg_count); | 270 Forget(frame_arg_count); |
| 271 } | 271 } |
| 272 | 272 |
| 273 | 273 |
| 274 bool VirtualFrame::RequiresMergeCode() { | 274 bool VirtualFrame::RequiresMergeCode() { |
| 275 // A frame requires merge code to be generated in the event that | 275 // A frame requires code to be generated to make the frame mergable if |
| 276 // there are duplicated non-synched registers or else elements not | 276 // there are duplicated non-synched registers or else valid elements not |
| 277 // in a (memory or register) location in the frame. We look for | 277 // in a (memory or register) location in the frame. We look for valid |
| 278 // non-synced non-location elements and count occurrences of | 278 // non-synced non-location elements and count occurrences of non-synced |
| 279 // non-synced registers. | 279 // registers. |
| 280 RegisterFile non_synced_regs; | 280 RegisterFile non_synced_regs; |
| 281 for (int i = 0; i < elements_.length(); i++) { | 281 for (int i = 0; i < elements_.length(); i++) { |
| 282 FrameElement element = elements_[i]; | 282 FrameElement element = elements_[i]; |
| 283 if (!element.is_synced()) { | 283 if (element.is_valid() && !element.is_synced()) { |
| 284 if (element.is_register()) { | 284 if (element.is_register()) { |
| 285 non_synced_regs.Use(elements_[i].reg()); | 285 non_synced_regs.Use(elements_[i].reg()); |
| 286 } else if (!element.is_memory()) { | 286 } else if (!element.is_memory()) { |
| 287 // Not memory or register and not synced. | 287 // Not memory or register and not synced. |
| 288 return true; | 288 return true; |
| 289 } | 289 } |
| 290 } | 290 } |
| 291 } | 291 } |
| 292 | 292 |
| 293 for (int i = 0; i < RegisterFile::kNumRegisters; i++) { | 293 for (int i = 0; i < RegisterFile::kNumRegisters; i++) { |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 354 } else { | 354 } else { |
| 355 // The element is in memory or a singly-frame-referenced register. | 355 // The element is in memory or a singly-frame-referenced register. |
| 356 new_elements[i] = element; | 356 new_elements[i] = element; |
| 357 } | 357 } |
| 358 } | 358 } |
| 359 | 359 |
| 360 // Perform the moves. | 360 // Perform the moves. |
| 361 for (int i = 0; i < elements_.length(); i++) { | 361 for (int i = 0; i < elements_.length(); i++) { |
| 362 FrameElement source = elements_[i]; | 362 FrameElement source = elements_[i]; |
| 363 FrameElement target = new_elements[i]; | 363 FrameElement target = new_elements[i]; |
| 364 ASSERT(target.is_register() || target.is_memory()); | 364 ASSERT(!target.is_valid() || target.is_register() || target.is_memory()); |
| 365 if (target.is_register()) { | 365 if (target.is_register()) { |
| 366 if (source.is_constant()) { | 366 if (source.is_constant()) { |
| 367 __ Set(target.reg(), Immediate(source.handle())); | 367 __ Set(target.reg(), Immediate(source.handle())); |
| 368 } else if (source.is_register() && !source.reg().is(target.reg())) { | 368 } else if (source.is_register() && !source.reg().is(target.reg())) { |
| 369 __ mov(target.reg(), source.reg()); | 369 __ mov(target.reg(), source.reg()); |
| 370 } | 370 } |
| 371 elements_[i] = target; | 371 elements_[i] = target; |
| 372 } else { | 372 } else if (target.is_memory()) { |
| 373 // The target is memory. | |
| 374 if (!source.is_memory()) { | 373 if (!source.is_memory()) { |
| 375 // Spilling a source register would decrement its reference count, | 374 // Spilling a source register would decrement its reference count, |
| 376 // but we have already done that when computing new target elements, | 375 // but we have already done that when computing new target elements, |
| 377 // so we use a raw spill. | 376 // so we use a raw spill. |
| 378 RawSpillElementAt(i); | 377 RawSpillElementAt(i); |
| 379 } | 378 } |
| 380 } | 379 } |
| 380 // Invalid elements do not need to be moved. |
| 381 } | 381 } |
| 382 | 382 |
| 383 delete[] new_elements; | 383 delete[] new_elements; |
| 384 ASSERT(cgen_->HasValidEntryRegisters()); | 384 ASSERT(cgen_->HasValidEntryRegisters()); |
| 385 cgen_->SetFrame(original_frame); | 385 cgen_->SetFrame(original_frame); |
| 386 ASSERT(cgen_->HasValidEntryRegisters()); | 386 ASSERT(cgen_->HasValidEntryRegisters()); |
| 387 } | 387 } |
| 388 | 388 |
| 389 | 389 |
| 390 void VirtualFrame::MergeTo(VirtualFrame* expected) { | 390 void VirtualFrame::MergeTo(VirtualFrame* expected) { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 403 // Mergable frames have all elements in locations, either memory or | 403 // Mergable frames have all elements in locations, either memory or |
| 404 // register. We thus have a series of to-memory and to-register moves. | 404 // register. We thus have a series of to-memory and to-register moves. |
| 405 // First perform all to-memory moves, register-to-memory moves because | 405 // First perform all to-memory moves, register-to-memory moves because |
| 406 // they can free registers and constant-to-memory moves because they do | 406 // they can free registers and constant-to-memory moves because they do |
| 407 // not use registers. | 407 // not use registers. |
| 408 MergeMoveRegistersToMemory(expected); | 408 MergeMoveRegistersToMemory(expected); |
| 409 MergeMoveRegistersToRegisters(expected); | 409 MergeMoveRegistersToRegisters(expected); |
| 410 MergeMoveMemoryToRegisters(expected); | 410 MergeMoveMemoryToRegisters(expected); |
| 411 | 411 |
| 412 // At this point, the frames should be identical. | 412 // At this point, the frames should be identical. |
| 413 // TODO(): Consider an "equals" method for frames. |
| 413 ASSERT(stack_pointer_ == expected->stack_pointer_); | 414 ASSERT(stack_pointer_ == expected->stack_pointer_); |
| 414 #ifdef DEBUG | 415 #ifdef DEBUG |
| 415 for (int i = 0; i < elements_.length(); i++) { | 416 for (int i = 0; i < elements_.length(); i++) { |
| 416 FrameElement expect = expected->elements_[i]; | 417 FrameElement expect = expected->elements_[i]; |
| 417 if (expect.is_memory()) { | 418 if (!expect.is_valid()) { |
| 419 ASSERT(!elements_[i].is_valid()); |
| 420 } else if (expect.is_memory()) { |
| 418 ASSERT(elements_[i].is_memory()); | 421 ASSERT(elements_[i].is_memory()); |
| 419 ASSERT(elements_[i].is_synced() && expect.is_synced()); | 422 ASSERT(elements_[i].is_synced() && expect.is_synced()); |
| 420 } else if (expect.is_register()) { | 423 } else if (expect.is_register()) { |
| 421 ASSERT(elements_[i].is_register()); | 424 ASSERT(elements_[i].is_register()); |
| 422 ASSERT(elements_[i].reg().is(expect.reg())); | 425 ASSERT(elements_[i].reg().is(expect.reg())); |
| 423 ASSERT(elements_[i].is_synced() == expect.is_synced()); | 426 ASSERT(elements_[i].is_synced() == expect.is_synced()); |
| 424 } else { | 427 } else { |
| 425 ASSERT(expect.is_constant()); | 428 ASSERT(expect.is_constant()); |
| 426 ASSERT(elements_[i].is_constant()); | 429 ASSERT(elements_[i].is_constant()); |
| 427 ASSERT(elements_[i].handle().location() == | 430 ASSERT(elements_[i].handle().location() == |
| (...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 642 __ Set(temp.reg(), Immediate(undefined)); | 645 __ Set(temp.reg(), Immediate(undefined)); |
| 643 for (int i = 0; i < count; i++) { | 646 for (int i = 0; i < count; i++) { |
| 644 elements_.Add(initial_value); | 647 elements_.Add(initial_value); |
| 645 stack_pointer_++; | 648 stack_pointer_++; |
| 646 __ push(temp.reg()); | 649 __ push(temp.reg()); |
| 647 } | 650 } |
| 648 } | 651 } |
| 649 } | 652 } |
| 650 | 653 |
| 651 | 654 |
| 655 void VirtualFrame::SetElementAt(int index, Result* value) { |
| 656 int frame_index = elements_.length() - index - 1; |
| 657 ASSERT(frame_index >= 0); |
| 658 ASSERT(frame_index < elements_.length()); |
| 659 ASSERT(value->is_valid()); |
| 660 |
| 661 // TODO(): if the element is backed by the same register or the same |
| 662 // constant, consider preserving the sync bit. |
| 663 if (elements_[frame_index].is_register()) { |
| 664 Unuse(elements_[frame_index].reg()); |
| 665 } |
| 666 |
| 667 if (value->is_register()) { |
| 668 Use(value->reg()); |
| 669 elements_[frame_index] = |
| 670 FrameElement::RegisterElement(value->reg(), |
| 671 FrameElement::NOT_SYNCED); |
| 672 } else { |
| 673 ASSERT(value->is_constant()); |
| 674 elements_[frame_index] = |
| 675 FrameElement::ConstantElement(value->handle(), |
| 676 FrameElement::NOT_SYNCED); |
| 677 } |
| 678 |
| 679 value->Unuse(); |
| 680 } |
| 681 |
| 682 |
| 652 void VirtualFrame::LoadFrameSlotAt(int index) { | 683 void VirtualFrame::LoadFrameSlotAt(int index) { |
| 653 ASSERT(index >= 0); | 684 ASSERT(index >= 0); |
| 654 ASSERT(index < elements_.length()); | 685 ASSERT(index < elements_.length()); |
| 655 | 686 |
| 656 FrameElement element = elements_[index]; | 687 FrameElement element = elements_[index]; |
| 657 | 688 |
| 658 if (element.is_memory()) { | 689 if (element.is_memory()) { |
| 659 ASSERT(index <= stack_pointer_); | 690 ASSERT(index <= stack_pointer_); |
| 660 // Eagerly load memory elements into a register. The element at | 691 // Eagerly load memory elements into a register. The element at |
| 661 // the index and the new top of the frame are backed by the same | 692 // the index and the new top of the frame are backed by the same |
| (...skipping 17 matching lines...) Expand all Loading... |
| 679 ASSERT(element.is_register() || element.is_constant()); | 710 ASSERT(element.is_register() || element.is_constant()); |
| 680 if (element.is_register()) { | 711 if (element.is_register()) { |
| 681 Use(element.reg()); | 712 Use(element.reg()); |
| 682 } | 713 } |
| 683 element.clear_sync(); | 714 element.clear_sync(); |
| 684 elements_.Add(element); | 715 elements_.Add(element); |
| 685 } | 716 } |
| 686 } | 717 } |
| 687 | 718 |
| 688 | 719 |
| 720 void VirtualFrame::TakeFrameSlotAt(int index) { |
| 721 LoadFrameSlotAt(index); |
| 722 |
| 723 if (elements_[index].is_register()) { |
| 724 Unuse(elements_[index].reg()); |
| 725 } |
| 726 elements_[index] = FrameElement::InvalidElement(); |
| 727 } |
| 728 |
| 729 |
| 689 void VirtualFrame::StoreToFrameSlotAt(int index) { | 730 void VirtualFrame::StoreToFrameSlotAt(int index) { |
| 690 // Store the value on top of the frame to the virtual frame slot at a | 731 // Store the value on top of the frame to the virtual frame slot at a |
| 691 // given index. The value on top of the frame is left in place. | 732 // given index. The value on top of the frame is left in place. |
| 692 ASSERT(index >= 0); | 733 ASSERT(index >= 0); |
| 693 ASSERT(index < elements_.length()); | 734 ASSERT(index < elements_.length()); |
| 694 FrameElement top = elements_[elements_.length() - 1]; | 735 FrameElement top = elements_[elements_.length() - 1]; |
| 695 | 736 |
| 696 if (elements_[index].is_register()) { | 737 if (elements_[index].is_register()) { |
| 697 Unuse(elements_[index].reg()); | 738 Unuse(elements_[index].reg()); |
| 698 } | 739 } |
| 699 // The virtual frame slot will be of the same type and have the same value | 740 // The virtual frame slot will be of the same type and have the same value |
| 700 // as the frame top. | 741 // as the frame top. |
| 701 elements_[index] = top; | 742 elements_[index] = top; |
| 702 | 743 |
| 703 if (top.is_memory()) { | 744 if (top.is_memory()) { |
| 745 // TODO(): consider allocating the slot to a register. |
| 746 // |
| 704 // Emit code to store memory values into the required frame slot. | 747 // Emit code to store memory values into the required frame slot. |
| 705 Result temp = cgen_->allocator()->Allocate(); | 748 Result temp = cgen_->allocator()->Allocate(); |
| 706 ASSERT(temp.is_valid()); | 749 ASSERT(temp.is_valid()); |
| 707 __ mov(temp.reg(), Top()); | 750 __ mov(temp.reg(), Top()); |
| 708 __ mov(Operand(ebp, fp_relative(index)), temp.reg()); | 751 __ mov(Operand(ebp, fp_relative(index)), temp.reg()); |
| 709 } else { | 752 } else { |
| 710 // We have not actually written the value to memory. | 753 // We have not actually written the value to memory. |
| 711 elements_[index].clear_sync(); | 754 elements_[index].clear_sync(); |
| 712 | 755 |
| 713 if (top.is_register()) { | 756 if (top.is_register()) { |
| (...skipping 18 matching lines...) Expand all Loading... |
| 732 | 775 |
| 733 | 776 |
| 734 void VirtualFrame::CallStub(CodeStub* stub, int frame_arg_count) { | 777 void VirtualFrame::CallStub(CodeStub* stub, int frame_arg_count) { |
| 735 ASSERT(cgen_->HasValidEntryRegisters()); | 778 ASSERT(cgen_->HasValidEntryRegisters()); |
| 736 PrepareForCall(frame_arg_count); | 779 PrepareForCall(frame_arg_count); |
| 737 __ CallStub(stub); | 780 __ CallStub(stub); |
| 738 } | 781 } |
| 739 | 782 |
| 740 | 783 |
| 741 Result VirtualFrame::CallStub(CodeStub* stub, | 784 Result VirtualFrame::CallStub(CodeStub* stub, |
| 785 Result* arg, |
| 786 int frame_arg_count) { |
| 787 arg->Unuse(); |
| 788 CallStub(stub, frame_arg_count); |
| 789 Result result = cgen_->allocator()->Allocate(eax); |
| 790 ASSERT(result.is_valid()); |
| 791 return result; |
| 792 } |
| 793 |
| 794 |
| 795 Result VirtualFrame::CallStub(CodeStub* stub, |
| 742 Result* arg0, | 796 Result* arg0, |
| 743 Result* arg1, | 797 Result* arg1, |
| 744 int frame_arg_count) { | 798 int frame_arg_count) { |
| 745 arg0->Unuse(); | 799 arg0->Unuse(); |
| 746 arg1->Unuse(); | 800 arg1->Unuse(); |
| 747 CallStub(stub, frame_arg_count); | 801 CallStub(stub, frame_arg_count); |
| 748 Result result = cgen_->allocator()->Allocate(eax); | 802 Result result = cgen_->allocator()->Allocate(eax); |
| 749 ASSERT(result.is_valid()); | 803 ASSERT(result.is_valid()); |
| 750 return result; | 804 return result; |
| 751 } | 805 } |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 907 return false; | 961 return false; |
| 908 } | 962 } |
| 909 } | 963 } |
| 910 return true; | 964 return true; |
| 911 } | 965 } |
| 912 #endif | 966 #endif |
| 913 | 967 |
| 914 #undef __ | 968 #undef __ |
| 915 | 969 |
| 916 } } // namespace v8::internal | 970 } } // namespace v8::internal |
| OLD | NEW |