Chromium Code Reviews| 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 17 matching lines...) Expand all Loading... | |
| 28 #include "v8.h" | 28 #include "v8.h" |
| 29 | 29 |
| 30 #include "codegen.h" | 30 #include "codegen.h" |
| 31 #include "codegen-inl.h" | 31 #include "codegen-inl.h" |
| 32 #include "virtual-frame.h" | 32 #include "virtual-frame.h" |
| 33 | 33 |
| 34 namespace v8 { namespace internal { | 34 namespace v8 { namespace internal { |
| 35 | 35 |
| 36 #define __ masm_-> | 36 #define __ masm_-> |
| 37 | 37 |
| 38 | |
| 39 // ------------------------------------------------------------------------- | |
| 40 // Result implementation. | |
| 41 | |
| 42 | |
| 43 Result::Result(Register reg, CodeGenerator* cgen) | |
| 44 : type_(REGISTER), | |
| 45 cgen_(cgen) { | |
| 46 data_.reg_ = reg; | |
| 47 ASSERT(!reg.is(no_reg)); | |
| 48 cgen_->allocator()->Use(reg); | |
| 49 } | |
| 50 | |
| 51 | |
| 52 void Result::Unuse() { | |
| 53 if (is_register()) { | |
| 54 cgen_->allocator()->Unuse(reg()); | |
| 55 } | |
| 56 type_ = INVALID; | |
| 57 } | |
| 58 | |
| 59 | |
| 60 void Result::ToRegister() { | |
| 61 ASSERT(is_valid()); | |
| 62 if (is_constant()) { | |
| 63 Register reg = cgen_->allocator()->Allocate(); | |
| 64 ASSERT(!reg.is(no_reg)); | |
| 65 cgen_->masm()->Set(reg, Immediate(handle())); | |
| 66 data_.reg_ = reg; | |
| 67 type_ = REGISTER; | |
| 68 } | |
| 69 ASSERT(is_register()); | |
| 70 } | |
| 71 | |
| 72 | |
| 73 // ------------------------------------------------------------------------- | 38 // ------------------------------------------------------------------------- |
| 74 // VirtualFrame implementation. | 39 // VirtualFrame implementation. |
| 75 | 40 |
| 76 VirtualFrame::SpilledScope::SpilledScope(CodeGenerator* cgen) | 41 VirtualFrame::SpilledScope::SpilledScope(CodeGenerator* cgen) |
| 77 : cgen_(cgen), | 42 : cgen_(cgen), |
| 78 previous_state_(cgen->in_spilled_code()) { | 43 previous_state_(cgen->in_spilled_code()) { |
| 79 ASSERT(cgen->frame() != NULL); | 44 ASSERT(cgen->frame() != NULL); |
| 80 cgen->frame()->SpillAll(); | 45 cgen->frame()->SpillAll(); |
| 81 cgen->set_in_spilled_code(true); | 46 cgen->set_in_spilled_code(true); |
| 82 } | 47 } |
| (...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 374 // multiply referenced, it is the lowermost occurrence that gets to | 339 // multiply referenced, it is the lowermost occurrence that gets to |
| 375 // stay in the register.) | 340 // stay in the register.) |
| 376 | 341 |
| 377 // The elements of new_elements are initially invalid. | 342 // The elements of new_elements are initially invalid. |
| 378 FrameElement* new_elements = new FrameElement[elements_.length()]; | 343 FrameElement* new_elements = new FrameElement[elements_.length()]; |
| 379 FrameElement memory_element = FrameElement::MemoryElement(); | 344 FrameElement memory_element = FrameElement::MemoryElement(); |
| 380 for (int i = elements_.length() - 1; i >= 0; i--) { | 345 for (int i = elements_.length() - 1; i >= 0; i--) { |
| 381 FrameElement element = elements_[i]; | 346 FrameElement element = elements_[i]; |
| 382 if (element.is_constant() || | 347 if (element.is_constant() || |
| 383 (element.is_register() && | 348 (element.is_register() && |
| 384 frame_registers_.count(element.reg().code()) > 1)) { | 349 frame_registers_.count(element.reg().code()) > 1)) { |
|
William Hesse
2008/12/19 08:41:03
Shouldn't we overload count() and is_used() to tak
Kevin Millikin (Chromium)
2008/12/19 08:48:11
Good idea. You want to do it :)
| |
| 385 // A simple strategy is to locate these elements in memory if they are | 350 // A simple strategy is to locate these elements in memory if they are |
| 386 // synced (avoiding a spill right now) and otherwise to prefer a | 351 // synced (avoiding a spill right now) and otherwise to prefer a |
| 387 // register for them. | 352 // register for them. |
| 388 if (element.is_synced()) { | 353 if (element.is_synced()) { |
| 389 new_elements[i] = memory_element; | 354 new_elements[i] = memory_element; |
| 390 } else { | 355 } else { |
| 391 Register reg = cgen_->allocator()->AllocateWithoutSpilling(); | 356 Result fresh = cgen_->allocator()->AllocateWithoutSpilling(); |
| 392 if (reg.is(no_reg)) { | 357 if (fresh.is_valid()) { |
| 358 // We immediately record the frame's use of the register so that | |
| 359 // it will not be allocated again. | |
| 360 Use(fresh.reg()); | |
| 361 new_elements[i] = | |
| 362 FrameElement::RegisterElement(fresh.reg(), | |
| 363 FrameElement::NOT_SYNCED); | |
| 364 } else { | |
| 393 new_elements[i] = memory_element; | 365 new_elements[i] = memory_element; |
| 394 } else { | |
| 395 new_elements[i] = | |
| 396 FrameElement::RegisterElement(reg, FrameElement::NOT_SYNCED); | |
| 397 } | 366 } |
| 398 } | 367 } |
| 399 | 368 |
| 400 // We have not moved register references, but record that we will so | 369 // We have not moved register references, but record that we will so |
| 401 // that we do not unnecessarily spill the last reference within the | 370 // that we do not unnecessarily spill the last reference within the |
| 402 // frame. | 371 // frame. |
| 403 if (element.is_register()) { | 372 if (element.is_register()) { |
| 404 Unuse(element.reg()); | 373 Unuse(element.reg()); |
| 405 } | 374 } |
| 406 } else { | 375 } else { |
| 407 // The element is in memory or a singly-frame-referenced register. | 376 // The element is in memory or a singly-frame-referenced register. |
| 408 new_elements[i] = element; | 377 new_elements[i] = element; |
| 409 } | 378 } |
| 410 } | 379 } |
| 411 | 380 |
| 412 // Perform the moves. | 381 // Perform the moves. |
| 413 for (int i = 0; i < elements_.length(); i++) { | 382 for (int i = 0; i < elements_.length(); i++) { |
| 414 FrameElement source = elements_[i]; | 383 FrameElement source = elements_[i]; |
| 415 FrameElement target = new_elements[i]; | 384 FrameElement target = new_elements[i]; |
| 416 ASSERT(target.is_register() || target.is_memory()); | 385 ASSERT(target.is_register() || target.is_memory()); |
| 417 if (target.is_register()) { | 386 if (target.is_register()) { |
| 418 if (source.is_constant()) { | 387 if (source.is_constant()) { |
| 419 // The allocator's register reference count was incremented by | |
| 420 // register allocation, so we only record the new reference in the | |
| 421 // frame. The frame now owns the reference. | |
| 422 frame_registers_.Use(target.reg()); | |
| 423 __ Set(target.reg(), Immediate(source.handle())); | 388 __ Set(target.reg(), Immediate(source.handle())); |
| 424 } else if (source.is_register() && !source.reg().is(target.reg())) { | 389 } else if (source.is_register() && !source.reg().is(target.reg())) { |
| 425 // The frame now owns the reference. | |
| 426 frame_registers_.Use(target.reg()); | |
| 427 __ mov(target.reg(), source.reg()); | 390 __ mov(target.reg(), source.reg()); |
| 428 } | 391 } |
| 429 elements_[i] = target; | 392 elements_[i] = target; |
| 430 } else { | 393 } else { |
| 431 // The target is memory. | 394 // The target is memory. |
| 432 if (!source.is_memory()) { | 395 if (!source.is_memory()) { |
| 433 // Spilling a source register would decrement its reference count, | 396 // Spilling a source register would decrement its reference count, |
| 434 // but we have already done that when computing new target elements, | 397 // but we have already done that when computing new target elements, |
| 435 // so we use a raw spill. | 398 // so we use a raw spill. |
| 436 RawSpillElementAt(i); | 399 RawSpillElementAt(i); |
| (...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 681 if (count > 0) { | 644 if (count > 0) { |
| 682 Comment cmnt(masm_, "[ Allocate space for locals"); | 645 Comment cmnt(masm_, "[ Allocate space for locals"); |
| 683 // The locals are initialized to a constant (the undefined value), but | 646 // The locals are initialized to a constant (the undefined value), but |
| 684 // we sync them with the actual frame to allocate space for spilling | 647 // we sync them with the actual frame to allocate space for spilling |
| 685 // them later. First sync everything above the stack pointer so we can | 648 // them later. First sync everything above the stack pointer so we can |
| 686 // use pushes to allocate and initialize the locals. | 649 // use pushes to allocate and initialize the locals. |
| 687 SyncRange(stack_pointer_ + 1, elements_.length()); | 650 SyncRange(stack_pointer_ + 1, elements_.length()); |
| 688 Handle<Object> undefined = Factory::undefined_value(); | 651 Handle<Object> undefined = Factory::undefined_value(); |
| 689 FrameElement initial_value = | 652 FrameElement initial_value = |
| 690 FrameElement::ConstantElement(undefined, FrameElement::SYNCED); | 653 FrameElement::ConstantElement(undefined, FrameElement::SYNCED); |
| 691 Register temp = cgen_->allocator()->Allocate(); | 654 Result temp = cgen_->allocator()->Allocate(); |
| 692 __ Set(temp, Immediate(undefined)); | 655 ASSERT(temp.is_valid()); |
| 656 __ Set(temp.reg(), Immediate(undefined)); | |
| 693 for (int i = 0; i < count; i++) { | 657 for (int i = 0; i < count; i++) { |
| 694 elements_.Add(initial_value); | 658 elements_.Add(initial_value); |
| 695 stack_pointer_++; | 659 stack_pointer_++; |
| 696 __ push(temp); | 660 __ push(temp.reg()); |
| 697 } | 661 } |
| 698 cgen_->allocator()->Unuse(temp); | |
| 699 } | 662 } |
| 700 } | 663 } |
| 701 | 664 |
| 702 | 665 |
| 703 void VirtualFrame::LoadFrameSlotAt(int index) { | 666 void VirtualFrame::LoadFrameSlotAt(int index) { |
| 704 ASSERT(index >= 0); | 667 ASSERT(index >= 0); |
| 705 ASSERT(index < elements_.length()); | 668 ASSERT(index < elements_.length()); |
| 706 | 669 |
| 707 FrameElement element = elements_[index]; | 670 FrameElement element = elements_[index]; |
| 708 | 671 |
| 709 if (element.is_memory()) { | 672 if (element.is_memory()) { |
| 710 ASSERT(index <= stack_pointer_); | 673 ASSERT(index <= stack_pointer_); |
| 711 // Eagerly load memory elements into a register. The element at | 674 // Eagerly load memory elements into a register. The element at |
| 712 // the index and the new top of the frame are backed by the same | 675 // the index and the new top of the frame are backed by the same |
| 713 // register location. | 676 // register location. |
| 714 Register temp = cgen_->allocator()->Allocate(); | 677 Result temp = cgen_->allocator()->Allocate(); |
| 715 ASSERT(!temp.is(no_reg)); | 678 ASSERT(temp.is_valid()); |
| 716 FrameElement new_element | 679 FrameElement new_element |
| 717 = FrameElement::RegisterElement(temp, FrameElement::NOT_SYNCED); | 680 = FrameElement::RegisterElement(temp.reg(), |
| 718 Use(temp); | 681 FrameElement::NOT_SYNCED); |
| 682 Use(temp.reg()); | |
| 719 elements_[index] = new_element; | 683 elements_[index] = new_element; |
| 720 Use(temp); | 684 Use(temp.reg()); |
| 721 elements_.Add(new_element); | 685 elements_.Add(new_element); |
| 722 | 686 |
| 723 // Finally, move the element at the index into its new location. | 687 // Finally, move the element at the index into its new location. |
| 724 elements_[index].set_sync(); | 688 elements_[index].set_sync(); |
| 725 __ mov(temp, Operand(ebp, fp_relative(index))); | 689 __ mov(temp.reg(), Operand(ebp, fp_relative(index))); |
| 726 | |
| 727 cgen_->allocator()->Unuse(temp); | |
| 728 } else { | 690 } else { |
| 729 // For constants and registers, add an (unsynced) copy of the element to | 691 // For constants and registers, add an (unsynced) copy of the element to |
| 730 // the top of the frame. | 692 // the top of the frame. |
| 731 ASSERT(element.is_register() || element.is_constant()); | 693 ASSERT(element.is_register() || element.is_constant()); |
| 732 if (element.is_register()) { | 694 if (element.is_register()) { |
| 733 Use(element.reg()); | 695 Use(element.reg()); |
| 734 } | 696 } |
| 735 element.clear_sync(); | 697 element.clear_sync(); |
| 736 elements_.Add(element); | 698 elements_.Add(element); |
| 737 } | 699 } |
| 738 } | 700 } |
| 739 | 701 |
| 740 | 702 |
| 741 void VirtualFrame::StoreToFrameSlotAt(int index) { | 703 void VirtualFrame::StoreToFrameSlotAt(int index) { |
| 742 // Store the value on top of the frame to the virtual frame slot at a | 704 // Store the value on top of the frame to the virtual frame slot at a |
| 743 // given index. The value on top of the frame is left in place. | 705 // given index. The value on top of the frame is left in place. |
| 744 ASSERT(index >= 0); | 706 ASSERT(index >= 0); |
| 745 ASSERT(index < elements_.length()); | 707 ASSERT(index < elements_.length()); |
| 746 FrameElement top = elements_[elements_.length() - 1]; | 708 FrameElement top = elements_[elements_.length() - 1]; |
| 747 | 709 |
| 748 if (elements_[index].is_register()) { | 710 if (elements_[index].is_register()) { |
| 749 Unuse(elements_[index].reg()); | 711 Unuse(elements_[index].reg()); |
| 750 } | 712 } |
| 751 // The virtual frame slot will be of the same type and have the same value | 713 // The virtual frame slot will be of the same type and have the same value |
| 752 // as the frame top. | 714 // as the frame top. |
| 753 elements_[index] = top; | 715 elements_[index] = top; |
| 754 | 716 |
| 755 if (top.is_memory()) { | 717 if (top.is_memory()) { |
| 756 // Emit code to store memory values into the required frame slot. | 718 // Emit code to store memory values into the required frame slot. |
| 757 Register temp = cgen_->allocator()->Allocate(); | 719 Result temp = cgen_->allocator()->Allocate(); |
| 758 ASSERT(!temp.is(no_reg)); | 720 ASSERT(temp.is_valid()); |
| 759 __ mov(temp, Top()); | 721 __ mov(temp.reg(), Top()); |
| 760 __ mov(Operand(ebp, fp_relative(index)), temp); | 722 __ mov(Operand(ebp, fp_relative(index)), temp.reg()); |
| 761 cgen_->allocator()->Unuse(temp); | |
| 762 } else { | 723 } else { |
| 763 // We have not actually written the value to memory. | 724 // We have not actually written the value to memory. |
| 764 elements_[index].clear_sync(); | 725 elements_[index].clear_sync(); |
| 765 | 726 |
| 766 if (top.is_register()) { | 727 if (top.is_register()) { |
| 767 // Establish another frame-internal reference to the register. | 728 // Establish another frame-internal reference to the register. |
| 768 Use(top.reg()); | 729 Use(top.reg()); |
| 769 } | 730 } |
| 770 } | 731 } |
| 771 } | 732 } |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 864 return Result(popped.handle(), cgen_); | 825 return Result(popped.handle(), cgen_); |
| 865 } else if (popped.is_register()) { | 826 } else if (popped.is_register()) { |
| 866 Unuse(popped.reg()); | 827 Unuse(popped.reg()); |
| 867 if (pop_needed) { | 828 if (pop_needed) { |
| 868 stack_pointer_--; | 829 stack_pointer_--; |
| 869 __ add(Operand(esp), Immediate(kPointerSize)); | 830 __ add(Operand(esp), Immediate(kPointerSize)); |
| 870 } | 831 } |
| 871 return Result(popped.reg(), cgen_); | 832 return Result(popped.reg(), cgen_); |
| 872 } else { | 833 } else { |
| 873 ASSERT(popped.is_memory()); | 834 ASSERT(popped.is_memory()); |
| 874 Register temp = cgen_->allocator()->Allocate(); | 835 Result temp = cgen_->allocator()->Allocate(); |
| 875 ASSERT(!temp.is(no_reg)); | 836 ASSERT(temp.is_valid()); |
| 876 ASSERT(pop_needed); | 837 ASSERT(pop_needed); |
| 877 stack_pointer_--; | 838 stack_pointer_--; |
| 878 __ pop(temp); | 839 __ pop(temp.reg()); |
| 879 // The register temp is double counted, by Allocate and Result(temp). | 840 return temp; |
| 880 cgen_->allocator()->Unuse(temp); | |
| 881 return Result(temp, cgen_); | |
| 882 } | 841 } |
| 883 } | 842 } |
| 884 | 843 |
| 885 void VirtualFrame::EmitPop(Register reg) { | 844 void VirtualFrame::EmitPop(Register reg) { |
| 886 ASSERT(stack_pointer_ == elements_.length() - 1); | 845 ASSERT(stack_pointer_ == elements_.length() - 1); |
| 887 stack_pointer_--; | 846 stack_pointer_--; |
| 888 elements_.RemoveLast(); | 847 elements_.RemoveLast(); |
| 889 __ pop(reg); | 848 __ pop(reg); |
| 890 } | 849 } |
| 891 | 850 |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 928 FrameElement::NOT_SYNCED)); | 887 FrameElement::NOT_SYNCED)); |
| 929 } | 888 } |
| 930 | 889 |
| 931 | 890 |
| 932 void VirtualFrame::Push(Handle<Object> value) { | 891 void VirtualFrame::Push(Handle<Object> value) { |
| 933 elements_.Add(FrameElement::ConstantElement(value, | 892 elements_.Add(FrameElement::ConstantElement(value, |
| 934 FrameElement::NOT_SYNCED)); | 893 FrameElement::NOT_SYNCED)); |
| 935 } | 894 } |
| 936 | 895 |
| 937 | 896 |
| 897 void VirtualFrame::Push(Result* result) { | |
| 898 if (result->is_register()) { | |
| 899 Push(result->reg()); | |
| 900 } else { | |
| 901 ASSERT(result->is_constant()); | |
| 902 Push(result->handle()); | |
| 903 } | |
| 904 result->Unuse(); | |
| 905 } | |
| 906 | |
| 907 | |
| 938 #ifdef DEBUG | 908 #ifdef DEBUG |
| 939 bool VirtualFrame::IsSpilled() { | 909 bool VirtualFrame::IsSpilled() { |
| 940 for (int i = 0; i < elements_.length(); i++) { | 910 for (int i = 0; i < elements_.length(); i++) { |
| 941 if (!elements_[i].is_memory()) { | 911 if (!elements_[i].is_memory()) { |
| 942 return false; | 912 return false; |
| 943 } | 913 } |
| 944 } | 914 } |
| 945 return true; | 915 return true; |
| 946 } | 916 } |
| 947 #endif | 917 #endif |
| 948 | 918 |
| 949 #undef __ | 919 #undef __ |
| 950 | 920 |
| 951 } } // namespace v8::internal | 921 } } // namespace v8::internal |
| OLD | NEW |