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

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

Issue 15037: Experimental: use the Result class to manage the lifetime of registers... (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/toiger/
Patch Set: '' Created 12 years 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
« src/register-allocator-ia32.cc ('K') | « 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 17 matching lines...) Expand all
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
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
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
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
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
OLDNEW
« src/register-allocator-ia32.cc ('K') | « src/virtual-frame-ia32.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698