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

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

Issue 15079: Experimental: this is a substantial change to allow the virtual frame... (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 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
124 cgen_->allocator()->Use(reg); 124 cgen_->allocator()->Use(reg);
125 } 125 }
126 126
127 127
128 void VirtualFrame::Unuse(Register reg) { 128 void VirtualFrame::Unuse(Register reg) {
129 frame_registers_.Unuse(reg); 129 frame_registers_.Unuse(reg);
130 cgen_->allocator()->Unuse(reg); 130 cgen_->allocator()->Unuse(reg);
131 } 131 }
132 132
133 133
134 // Spill any register if possible, making its reference count zero. 134 void VirtualFrame::Spill(Register target) {
135 for (int i = 0; i < elements_.length(); i++) {
136 if (elements_[i].is_register() && elements_[i].reg().is(target)) {
137 SpillElementAt(i);
138 }
139 }
140 }
141
142
143 // Spill any register if possible, making its external reference count zero.
135 Register VirtualFrame::SpillAnyRegister() { 144 Register VirtualFrame::SpillAnyRegister() {
136 // Find the leftmost (ordered by register code), least 145 // Find the leftmost (ordered by register code), least
137 // internally-referenced register whose internal reference count matches 146 // internally-referenced register whose internal reference count matches
138 // its external reference count (so that spilling it from the frame frees 147 // its external reference count (so that spilling it from the frame frees
139 // it for use). 148 // it for use).
140 int min_count = kMaxInt; 149 int min_count = kMaxInt;
141 int best_register_code = no_reg.code_; 150 int best_register_code = no_reg.code_;
142 151
143 for (int i = 0; i < RegisterFile::kNumRegisters; i++) { 152 for (int i = 0; i < RegisterFile::kNumRegisters; i++) {
144 int count = frame_registers_.count(i); 153 int count = frame_registers_.count(i);
145 if (count < min_count && count == cgen_->allocator()->count(i)) { 154 if (count < min_count && count == cgen_->allocator()->count(i)) {
146 min_count = count; 155 min_count = count;
147 best_register_code = i; 156 best_register_code = i;
148 } 157 }
149 } 158 }
150 159
151 if (best_register_code != no_reg.code_) { 160 Register result = { best_register_code };
152 // Spill all occurrences of the register. There are min_count 161 if (result.is_valid()) {
153 // occurrences, stop when we have spilled them all to avoid syncing 162 Spill(result);
154 // elements unnecessarily. 163 ASSERT(!cgen_->allocator()->is_used(result));
155 int i = 0;
156 while (min_count > 0) {
157 ASSERT(i < elements_.length());
158 if (elements_[i].is_register() &&
159 elements_[i].reg().code() == best_register_code) {
160 // Found an instance of the best_register being used in the frame.
161 // Spill it.
162 SpillElementAt(i);
163 min_count--;
164 }
165 i++;
166 }
167 } 164 }
168
169 ASSERT(cgen_->allocator()->count(best_register_code) == 0);
170 Register result = { best_register_code };
171 return result; 165 return result;
172 } 166 }
173 167
174 168
175 // Spill an element, making its type be MEMORY. 169 // Spill an element, making its type be MEMORY.
176 // Does not decrement usage counts, if element is a register. 170 // Does not decrement usage counts, if element is a register.
177 void VirtualFrame::RawSpillElementAt(int index) { 171 void VirtualFrame::RawSpillElementAt(int index) {
178 SyncElementAt(index); 172 SyncElementAt(index);
179 // The element is now in memory. 173 // The element is now in memory.
180 elements_[index] = FrameElement::MemoryElement(); 174 elements_[index] = FrameElement::MemoryElement();
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
270 } else { 264 } else {
271 SyncElementAt(i); 265 SyncElementAt(i);
272 } 266 }
273 } 267 }
274 268
275 // Forget the frame elements that will be popped by the call. 269 // Forget the frame elements that will be popped by the call.
276 Forget(frame_arg_count); 270 Forget(frame_arg_count);
277 } 271 }
278 272
279 273
280 bool VirtualFrame::IsMergable() {
281 // We cannot merge to a frame that has constants as elements, because an
282 // arbitrary frame may not have the same constants at those locations. We
283 // cannot merge to a frame that has registers that are mulitply referenced
284 // in the frame, because an arbitrary frame might not exhibit the same
285 // sharing. Thus, a frame is mergable if all elements are in memory or a
286 // register and no register is multiply referenced.
287 for (int i = 0; i < RegisterFile::kNumRegisters; i++) {
288 if (frame_registers_.count(i) > 1) {
289 return false;
290 }
291 }
292
293 for (int i = 0; i < elements_.length(); i++) {
294 if (!elements_[i].is_memory() && !elements_[i].is_register()) {
295 return false;
296 }
297 }
298
299 return true;
300 }
301
302
303 bool VirtualFrame::RequiresMergeCode() { 274 bool VirtualFrame::RequiresMergeCode() {
304 // A frame requires merge code to be generated in the event that 275 // A frame requires merge code to be generated in the event that
305 // there are duplicated non-synched registers or else elements not 276 // there are duplicated non-synched registers or else elements not
306 // 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
307 // non-synced non-location elements and count occurrences of 278 // non-synced non-location elements and count occurrences of
308 // non-synced registers. 279 // non-synced registers.
309 RegisterFile non_synced_regs; 280 RegisterFile non_synced_regs;
310 for (int i = 0; i < elements_.length(); i++) { 281 for (int i = 0; i < elements_.length(); i++) {
311 FrameElement element = elements_[i]; 282 FrameElement element = elements_[i];
312 if (!element.is_synced()) { 283 if (!element.is_synced()) {
(...skipping 11 matching lines...) Expand all
324 return true; 295 return true;
325 } 296 }
326 } 297 }
327 298
328 return false; 299 return false;
329 } 300 }
330 301
331 302
332 void VirtualFrame::MakeMergable() { 303 void VirtualFrame::MakeMergable() {
333 Comment cmnt(masm_, "[ Make frame mergable"); 304 Comment cmnt(masm_, "[ Make frame mergable");
305 // We can call MakeMergable on a frame that is not the code generator's
306 // current frame, which will leave the global register counts out of sync
307 // with the frame. We simply save the current frame and restore it at the
308 // end of this function. We should find a better way to deal with this.
309 VirtualFrame* original_frame = cgen_->frame();
310 ASSERT(cgen_->HasValidEntryRegisters());
311 cgen_->SetFrame(this);
312 ASSERT(cgen_->HasValidEntryRegisters());
313
334 // Remove constants from the frame and ensure that no registers are 314 // Remove constants from the frame and ensure that no registers are
335 // multiply referenced within the frame. Allocate elements to their 315 // multiply referenced within the frame. Allocate elements to their new
336 // new locations from the top down so that the topmost elements have 316 // locations from the top down so that the topmost elements have a chance
337 // a chance to be in registers, then fill them into memory from the 317 // to be in registers, then fill them into memory from the bottom up.
338 // bottom up. (NB: Currently when spilling registers that are 318 // (NB: Currently when spilling registers that are multiply referenced, it
339 // multiply referenced, it is the lowermost occurrence that gets to 319 // is the lowermost occurrence that gets to stay in the register.)
340 // stay in the register.)
341 320
342 // The elements of new_elements are initially invalid. 321 // The elements of new_elements are initially invalid.
343 FrameElement* new_elements = new FrameElement[elements_.length()]; 322 FrameElement* new_elements = new FrameElement[elements_.length()];
344 FrameElement memory_element = FrameElement::MemoryElement(); 323 FrameElement memory_element = FrameElement::MemoryElement();
345 for (int i = elements_.length() - 1; i >= 0; i--) { 324 for (int i = elements_.length() - 1; i >= 0; i--) {
346 FrameElement element = elements_[i]; 325 FrameElement element = elements_[i];
347 if (element.is_constant() || 326 if (element.is_constant() ||
348 (element.is_register() && 327 (element.is_register() &&
349 frame_registers_.count(element.reg().code()) > 1)) { 328 frame_registers_.count(element.reg()) > 1)) {
350 // A simple strategy is to locate these elements in memory if they are 329 // A simple strategy is to locate these elements in memory if they are
351 // synced (avoiding a spill right now) and otherwise to prefer a 330 // synced (avoiding a spill right now) and otherwise to prefer a
352 // register for them. 331 // register for them.
353 if (element.is_synced()) { 332 if (element.is_synced()) {
354 new_elements[i] = memory_element; 333 new_elements[i] = memory_element;
355 } else { 334 } else {
356 Result fresh = cgen_->allocator()->AllocateWithoutSpilling(); 335 Result fresh = cgen_->allocator()->AllocateWithoutSpilling();
357 if (fresh.is_valid()) { 336 if (fresh.is_valid()) {
358 // We immediately record the frame's use of the register so that 337 // We immediately record the frame's use of the register so that
359 // it will not be allocated again. 338 // it will not be allocated again.
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
395 if (!source.is_memory()) { 374 if (!source.is_memory()) {
396 // Spilling a source register would decrement its reference count, 375 // Spilling a source register would decrement its reference count,
397 // but we have already done that when computing new target elements, 376 // but we have already done that when computing new target elements,
398 // so we use a raw spill. 377 // so we use a raw spill.
399 RawSpillElementAt(i); 378 RawSpillElementAt(i);
400 } 379 }
401 } 380 }
402 } 381 }
403 382
404 delete[] new_elements; 383 delete[] new_elements;
384 ASSERT(cgen_->HasValidEntryRegisters());
385 cgen_->SetFrame(original_frame);
386 ASSERT(cgen_->HasValidEntryRegisters());
405 } 387 }
406 388
407 389
408 void VirtualFrame::MergeTo(VirtualFrame* expected) { 390 void VirtualFrame::MergeTo(VirtualFrame* expected) {
409 Comment cmnt(masm_, "[ Merge frame"); 391 Comment cmnt(masm_, "[ Merge frame");
392 // We should always be merging the code generator's current frame to an
393 // expected frame.
394 ASSERT(cgen_->frame() == this);
395
410 ASSERT(cgen_ == expected->cgen_); 396 ASSERT(cgen_ == expected->cgen_);
411 ASSERT(masm_ == expected->masm_); 397 ASSERT(masm_ == expected->masm_);
412 ASSERT(elements_.length() == expected->elements_.length()); 398 ASSERT(elements_.length() == expected->elements_.length());
413 ASSERT(parameter_count_ == expected->parameter_count_); 399 ASSERT(parameter_count_ == expected->parameter_count_);
414 ASSERT(local_count_ == expected->local_count_); 400 ASSERT(local_count_ == expected->local_count_);
415 ASSERT(frame_pointer_ == expected->frame_pointer_); 401 ASSERT(frame_pointer_ == expected->frame_pointer_);
416 402
417 // Mergable frames have all elements in locations, either memory or 403 // Mergable frames have all elements in locations, either memory or
418 // 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.
419 // First perform all to-memory moves, register-to-memory moves because 405 // First perform all to-memory moves, register-to-memory moves because
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
474 FrameElement source = elements_[i]; 460 FrameElement source = elements_[i];
475 FrameElement target = expected->elements_[i]; 461 FrameElement target = expected->elements_[i];
476 if (source.is_register() && target.is_register()) { 462 if (source.is_register() && target.is_register()) {
477 if (target.reg().is(source.reg())) { 463 if (target.reg().is(source.reg())) {
478 if (target.is_synced() && !source.is_synced()) { 464 if (target.is_synced() && !source.is_synced()) {
479 SyncElementAt(i); 465 SyncElementAt(i);
480 } 466 }
481 elements_[i] = target; 467 elements_[i] = target;
482 } else { 468 } else {
483 // We need to move source to target. 469 // We need to move source to target.
484 if (frame_registers_.is_used(target.reg().code())) { 470 if (frame_registers_.is_used(target.reg())) {
485 // The move is blocked because the target contains valid data. 471 // The move is blocked because the target contains valid data.
486 // If we are stuck with only cycles remaining, then we spill source. 472 // If we are stuck with only cycles remaining, then we spill source.
487 // Otherwise, we just need more iterations. 473 // Otherwise, we just need more iterations.
488 if (should_break_cycles) { 474 if (should_break_cycles) {
489 SpillElementAt(i); 475 SpillElementAt(i);
490 should_break_cycles = false; 476 should_break_cycles = false;
491 } else { // Record a blocked move. 477 } else { // Record a blocked move.
492 if (!any_moves_blocked) { 478 if (!any_moves_blocked) {
493 first_move_blocked = i; 479 first_move_blocked = i;
494 } 480 }
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after
726 712
727 if (top.is_register()) { 713 if (top.is_register()) {
728 // Establish another frame-internal reference to the register. 714 // Establish another frame-internal reference to the register.
729 Use(top.reg()); 715 Use(top.reg());
730 } 716 }
731 } 717 }
732 } 718 }
733 719
734 720
735 void VirtualFrame::PushTryHandler(HandlerType type) { 721 void VirtualFrame::PushTryHandler(HandlerType type) {
722 ASSERT(cgen_->HasValidEntryRegisters());
736 // Grow the expression stack by handler size less two (the return address 723 // Grow the expression stack by handler size less two (the return address
737 // is already pushed by a call instruction, and PushTryHandler from the 724 // is already pushed by a call instruction, and PushTryHandler from the
738 // macro assembler will leave the top of stack in the eax register to be 725 // macro assembler will leave the top of stack in the eax register to be
739 // pushed separately). 726 // pushed separately).
740 Adjust(kHandlerSize - 2); 727 Adjust(kHandlerSize - 2);
741 __ PushTryHandler(IN_JAVASCRIPT, type); 728 __ PushTryHandler(IN_JAVASCRIPT, type);
742 // TODO(1222589): remove the reliance of PushTryHandler on a cached TOS 729 // TODO(1222589): remove the reliance of PushTryHandler on a cached TOS
743 EmitPush(eax); 730 EmitPush(eax);
744 } 731 }
745 732
746 733
747 void VirtualFrame::CallStub(CodeStub* stub, int frame_arg_count) { 734 void VirtualFrame::CallStub(CodeStub* stub, int frame_arg_count) {
735 ASSERT(cgen_->HasValidEntryRegisters());
748 PrepareForCall(frame_arg_count); 736 PrepareForCall(frame_arg_count);
749 __ CallStub(stub); 737 __ CallStub(stub);
750 } 738 }
751 739
752 740
741 Result VirtualFrame::CallStub(CodeStub* stub,
742 Result* arg0,
743 Result* arg1,
744 int frame_arg_count) {
745 arg0->Unuse();
746 arg1->Unuse();
747 CallStub(stub, frame_arg_count);
748 Result result = cgen_->allocator()->Allocate(eax);
749 ASSERT(result.is_valid());
750 return result;
751 }
752
753
753 void VirtualFrame::CallRuntime(Runtime::Function* f, int frame_arg_count) { 754 void VirtualFrame::CallRuntime(Runtime::Function* f, int frame_arg_count) {
755 ASSERT(cgen_->HasValidEntryRegisters());
754 PrepareForCall(frame_arg_count); 756 PrepareForCall(frame_arg_count);
755 __ CallRuntime(f, frame_arg_count); 757 __ CallRuntime(f, frame_arg_count);
756 } 758 }
757 759
758 760
759 void VirtualFrame::CallRuntime(Runtime::FunctionId id, int frame_arg_count) { 761 void VirtualFrame::CallRuntime(Runtime::FunctionId id, int frame_arg_count) {
762 ASSERT(cgen_->HasValidEntryRegisters());
760 PrepareForCall(frame_arg_count); 763 PrepareForCall(frame_arg_count);
761 __ CallRuntime(id, frame_arg_count); 764 __ CallRuntime(id, frame_arg_count);
762 } 765 }
763 766
764 767
765 void VirtualFrame::InvokeBuiltin(Builtins::JavaScript id, 768 void VirtualFrame::InvokeBuiltin(Builtins::JavaScript id,
766 InvokeFlag flag, 769 InvokeFlag flag,
767 int frame_arg_count) { 770 int frame_arg_count) {
771 ASSERT(cgen_->HasValidEntryRegisters());
768 PrepareForCall(frame_arg_count); 772 PrepareForCall(frame_arg_count);
769 __ InvokeBuiltin(id, flag); 773 __ InvokeBuiltin(id, flag);
770 } 774 }
771 775
772 776
773 void VirtualFrame::CallCodeObject(Handle<Code> code, 777 void VirtualFrame::CallCodeObject(Handle<Code> code,
774 RelocInfo::Mode rmode, 778 RelocInfo::Mode rmode,
775 int frame_arg_count) { 779 int frame_arg_count) {
780 ASSERT(cgen_->HasValidEntryRegisters());
776 PrepareForCall(frame_arg_count); 781 PrepareForCall(frame_arg_count);
777 __ call(code, rmode); 782 __ call(code, rmode);
778 } 783 }
779 784
780 785
781 void VirtualFrame::Drop(int count) { 786 void VirtualFrame::Drop(int count) {
782 ASSERT(height() >= count); 787 ASSERT(height() >= count);
783 int num_virtual_elements = (elements_.length() - 1) - stack_pointer_; 788 int num_virtual_elements = (elements_.length() - 1) - stack_pointer_;
784 789
785 // Emit code to lower the stack pointer if necessary. 790 // Emit code to lower the stack pointer if necessary.
786 if (num_virtual_elements < count) { 791 if (num_virtual_elements < count) {
787 int num_dropped = count - num_virtual_elements; 792 int num_dropped = count - num_virtual_elements;
788 stack_pointer_ -= num_dropped; 793 stack_pointer_ -= num_dropped;
789 __ add(Operand(esp), Immediate(num_dropped * kPointerSize)); 794 __ add(Operand(esp), Immediate(num_dropped * kPointerSize));
790 } 795 }
791 796
792 // Discard elements from the virtual frame and free any registers. 797 // Discard elements from the virtual frame and free any registers.
793 for (int i = 0; i < count; i++) { 798 for (int i = 0; i < count; i++) {
794 FrameElement dropped = elements_.RemoveLast(); 799 FrameElement dropped = elements_.RemoveLast();
795 if (dropped.is_register()) { 800 if (dropped.is_register()) {
796 Unuse(dropped.reg()); 801 Unuse(dropped.reg());
797 } 802 }
798 } 803 }
799 } 804 }
800 805
801 806
802 void VirtualFrame::Drop() { Drop(1); } 807 void VirtualFrame::Drop() { Drop(1); }
803 808
804 809
805 /*
806 We need comparison with literal to work.
807 It will get Result, is register or constant.
808 Pop gives it this, from register, constant, memory, or
809 reference to slot.
810
811 In comparison to literal, we need register case to work.
812 We need non-smi stub to exit and return with a non-spilled frame.
813 */
814
815
816 Result VirtualFrame::Pop() { 810 Result VirtualFrame::Pop() {
817 FrameElement popped = elements_.RemoveLast(); 811 FrameElement popped = elements_.RemoveLast();
818 bool pop_needed = (stack_pointer_ == elements_.length()); 812 bool pop_needed = (stack_pointer_ == elements_.length());
819 813
820 if (popped.is_constant()) { 814 if (popped.is_constant()) {
821 if (pop_needed) { 815 if (pop_needed) {
822 stack_pointer_--; 816 stack_pointer_--;
823 __ add(Operand(esp), Immediate(kPointerSize)); 817 __ add(Operand(esp), Immediate(kPointerSize));
824 } 818 }
825 return Result(popped.handle(), cgen_); 819 return Result(popped.handle(), cgen_);
826 } else if (popped.is_register()) { 820 } else if (popped.is_register()) {
827 Unuse(popped.reg()); 821 Unuse(popped.reg());
828 if (pop_needed) { 822 if (pop_needed) {
829 stack_pointer_--; 823 stack_pointer_--;
830 __ add(Operand(esp), Immediate(kPointerSize)); 824 __ add(Operand(esp), Immediate(kPointerSize));
831 } 825 }
832 return Result(popped.reg(), cgen_); 826 return Result(popped.reg(), cgen_);
833 } else { 827 } else {
834 ASSERT(popped.is_memory()); 828 ASSERT(popped.is_memory());
835 Result temp = cgen_->allocator()->Allocate(); 829 Result temp = cgen_->allocator()->Allocate();
836 ASSERT(temp.is_valid()); 830 ASSERT(temp.is_valid());
837 ASSERT(pop_needed); 831 ASSERT(pop_needed);
838 stack_pointer_--; 832 stack_pointer_--;
839 __ pop(temp.reg()); 833 __ pop(temp.reg());
840 return temp; 834 return temp;
841 } 835 }
842 } 836 }
843 837
838
844 void VirtualFrame::EmitPop(Register reg) { 839 void VirtualFrame::EmitPop(Register reg) {
845 ASSERT(stack_pointer_ == elements_.length() - 1); 840 ASSERT(stack_pointer_ == elements_.length() - 1);
846 stack_pointer_--; 841 stack_pointer_--;
847 elements_.RemoveLast(); 842 elements_.RemoveLast();
848 __ pop(reg); 843 __ pop(reg);
849 } 844 }
850 845
851 846
852 void VirtualFrame::EmitPop(Operand operand) { 847 void VirtualFrame::EmitPop(Operand operand) {
853 ASSERT(stack_pointer_ == elements_.length() - 1); 848 ASSERT(stack_pointer_ == elements_.length() - 1);
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
912 return false; 907 return false;
913 } 908 }
914 } 909 }
915 return true; 910 return true;
916 } 911 }
917 #endif 912 #endif
918 913
919 #undef __ 914 #undef __
920 915
921 } } // namespace v8::internal 916 } } // 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