| 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 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 90 // On entry to a function, the virtual frame already contains the receiver, | 90 // On entry to a function, the virtual frame already contains the receiver, |
| 91 // the parameters, and a return address. All frame elements are in memory. | 91 // the parameters, and a return address. All frame elements are in memory. |
| 92 VirtualFrame::VirtualFrame(CodeGenerator* cgen) | 92 VirtualFrame::VirtualFrame(CodeGenerator* cgen) |
| 93 : cgen_(cgen), | 93 : cgen_(cgen), |
| 94 masm_(cgen->masm()), | 94 masm_(cgen->masm()), |
| 95 elements_(0), | 95 elements_(0), |
| 96 parameter_count_(cgen->scope()->num_parameters()), | 96 parameter_count_(cgen->scope()->num_parameters()), |
| 97 local_count_(0), | 97 local_count_(0), |
| 98 stack_pointer_(parameter_count_ + 1), // 0-based index of TOS. | 98 stack_pointer_(parameter_count_ + 1), // 0-based index of TOS. |
| 99 frame_pointer_(kIllegalIndex) { | 99 frame_pointer_(kIllegalIndex) { |
| 100 FrameElement memory_element; | |
| 101 for (int i = 0; i < parameter_count_ + 2; i++) { | 100 for (int i = 0; i < parameter_count_ + 2; i++) { |
| 102 elements_.Add(memory_element); | 101 elements_.Add(FrameElement::MemoryElement()); |
| 103 } | 102 } |
| 104 } | 103 } |
| 105 | 104 |
| 106 | 105 |
| 107 // When cloned, a frame is a deep copy of the original. | 106 // When cloned, a frame is a deep copy of the original. |
| 108 VirtualFrame::VirtualFrame(VirtualFrame* original) | 107 VirtualFrame::VirtualFrame(VirtualFrame* original) |
| 109 : cgen_(original->cgen_), | 108 : cgen_(original->cgen_), |
| 110 masm_(original->masm_), | 109 masm_(original->masm_), |
| 111 elements_(original->elements_.length()), | 110 elements_(original->elements_.length()), |
| 112 parameter_count_(original->parameter_count_), | 111 parameter_count_(original->parameter_count_), |
| (...skipping 10 matching lines...) Expand all Loading... |
| 123 | 122 |
| 124 // Modify the state of the virtual frame to match the actual frame by adding | 123 // Modify the state of the virtual frame to match the actual frame by adding |
| 125 // extra in-memory elements to the top of the virtual frame. The extra | 124 // extra in-memory elements to the top of the virtual frame. The extra |
| 126 // elements will be externally materialized on the actual frame (eg, by | 125 // elements will be externally materialized on the actual frame (eg, by |
| 127 // pushing an exception handler). No code is emitted. | 126 // pushing an exception handler). No code is emitted. |
| 128 void VirtualFrame::Adjust(int count) { | 127 void VirtualFrame::Adjust(int count) { |
| 129 ASSERT(count >= 0); | 128 ASSERT(count >= 0); |
| 130 ASSERT(stack_pointer_ == elements_.length() - 1); | 129 ASSERT(stack_pointer_ == elements_.length() - 1); |
| 131 | 130 |
| 132 for (int i = 0; i < count; i++) { | 131 for (int i = 0; i < count; i++) { |
| 133 elements_.Add(FrameElement()); | 132 elements_.Add(FrameElement::MemoryElement()); |
| 134 } | 133 } |
| 135 stack_pointer_ += count; | 134 stack_pointer_ += count; |
| 136 } | 135 } |
| 137 | 136 |
| 138 | 137 |
| 139 // Modify the state of the virtual frame to match the actual frame by | 138 // Modify the state of the virtual frame to match the actual frame by |
| 140 // removing elements from the top of the virtual frame. The elements will | 139 // removing elements from the top of the virtual frame. The elements will |
| 141 // be externally popped from the actual frame (eg, by a runtime call). No | 140 // be externally popped from the actual frame (eg, by a runtime call). No |
| 142 // code is emitted. | 141 // code is emitted. |
| 143 void VirtualFrame::Forget(int count) { | 142 void VirtualFrame::Forget(int count) { |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 245 | 244 |
| 246 | 245 |
| 247 // Spill an element, making its type be MEMORY. If it is a register the | 246 // Spill an element, making its type be MEMORY. If it is a register the |
| 248 // reference count is not decremented, so it must be done externally. | 247 // reference count is not decremented, so it must be done externally. |
| 249 void VirtualFrame::RawSpillElementAt(int index) { | 248 void VirtualFrame::RawSpillElementAt(int index) { |
| 250 if (index > stack_pointer_ + 1) { | 249 if (index > stack_pointer_ + 1) { |
| 251 SyncRange(stack_pointer_ + 1, index); | 250 SyncRange(stack_pointer_ + 1, index); |
| 252 } | 251 } |
| 253 SyncElementAt(index); | 252 SyncElementAt(index); |
| 254 // The element is now in memory. | 253 // The element is now in memory. |
| 255 FrameElement memory_element; | 254 elements_[index] = FrameElement::MemoryElement(); |
| 256 elements_[index] = memory_element; | |
| 257 } | 255 } |
| 258 | 256 |
| 259 | 257 |
| 260 // Make the type of the element at a given index be MEMORY. We can only | 258 // Make the type of the element at a given index be MEMORY. We can only |
| 261 // allocate space in the actual frame for the virtual element immediately | 259 // allocate space in the actual frame for the virtual element immediately |
| 262 // above the stack pointer. | 260 // above the stack pointer. |
| 263 void VirtualFrame::SpillElementAt(int index) { | 261 void VirtualFrame::SpillElementAt(int index) { |
| 264 if (elements_[index].is_register()) { | 262 if (elements_[index].is_register()) { |
| 265 Unuse(elements_[index].reg()); | 263 Unuse(elements_[index].reg()); |
| 266 } | 264 } |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 365 | 363 |
| 366 void VirtualFrame::MakeMergable() { | 364 void VirtualFrame::MakeMergable() { |
| 367 Comment cmnt(masm_, "[ Make frame mergable"); | 365 Comment cmnt(masm_, "[ Make frame mergable"); |
| 368 // Remove constants from the frame and ensure that no registers are | 366 // Remove constants from the frame and ensure that no registers are |
| 369 // multiply referenced within the frame. Allocate elements to their | 367 // multiply referenced within the frame. Allocate elements to their |
| 370 // new locations from the top down so that the topmost elements have | 368 // new locations from the top down so that the topmost elements have |
| 371 // a chance to be in registers, then fill them into memory from the | 369 // a chance to be in registers, then fill them into memory from the |
| 372 // bottom up. (NB: Currently when spilling registers that are | 370 // bottom up. (NB: Currently when spilling registers that are |
| 373 // multiply referenced, it is the lowermost occurrence that gets to | 371 // multiply referenced, it is the lowermost occurrence that gets to |
| 374 // stay in the register.) | 372 // stay in the register.) |
| 373 |
| 374 // The elements of new_elements are initially invalid. |
| 375 FrameElement* new_elements = new FrameElement[elements_.length()]; | 375 FrameElement* new_elements = new FrameElement[elements_.length()]; |
| 376 FrameElement memory_element; | 376 FrameElement memory_element = FrameElement::MemoryElement(); |
| 377 for (int i = elements_.length() - 1; i >= 0; i--) { | 377 for (int i = elements_.length() - 1; i >= 0; i--) { |
| 378 FrameElement element = elements_[i]; | 378 FrameElement element = elements_[i]; |
| 379 if (element.is_constant() || | 379 if (element.is_constant() || |
| 380 (element.is_register() && | 380 (element.is_register() && |
| 381 frame_registers_.count(element.reg().code()) > 1)) { | 381 frame_registers_.count(element.reg().code()) > 1)) { |
| 382 // A simple strategy is to locate these elements in memory if they are | 382 // A simple strategy is to locate these elements in memory if they are |
| 383 // synced (avoiding a spill right now) and otherwise to prefer a | 383 // synced (avoiding a spill right now) and otherwise to prefer a |
| 384 // register for them. | 384 // register for them. |
| 385 if (element.is_synced()) { | 385 if (element.is_synced()) { |
| 386 new_elements[i] = memory_element; | 386 new_elements[i] = memory_element; |
| 387 } else { | 387 } else { |
| 388 Register reg = cgen_->allocator()->AllocateWithoutSpilling(); | 388 Register reg = cgen_->allocator()->AllocateWithoutSpilling(); |
| 389 if (reg.is(no_reg)) { | 389 if (reg.is(no_reg)) { |
| 390 new_elements[i] = memory_element; | 390 new_elements[i] = memory_element; |
| 391 } else { | 391 } else { |
| 392 FrameElement register_element(reg, FrameElement::NOT_SYNCED); | 392 new_elements[i] = |
| 393 new_elements[i] = register_element; | 393 FrameElement::RegisterElement(reg, FrameElement::NOT_SYNCED); |
| 394 } | 394 } |
| 395 } | 395 } |
| 396 | 396 |
| 397 // We have not moved register references, but record that we will so | 397 // We have not moved register references, but record that we will so |
| 398 // that we do not unnecessarily spill the last reference within the | 398 // that we do not unnecessarily spill the last reference within the |
| 399 // frame. | 399 // frame. |
| 400 if (element.is_register()) { | 400 if (element.is_register()) { |
| 401 Unuse(element.reg()); | 401 Unuse(element.reg()); |
| 402 } | 402 } |
| 403 } else { | 403 } else { |
| (...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 663 local_count_ = count; | 663 local_count_ = count; |
| 664 | 664 |
| 665 if (count > 0) { | 665 if (count > 0) { |
| 666 Comment cmnt(masm_, "[ Allocate space for locals"); | 666 Comment cmnt(masm_, "[ Allocate space for locals"); |
| 667 // The locals are initialized to a constant (the undefined value), but | 667 // The locals are initialized to a constant (the undefined value), but |
| 668 // we sync them with the actual frame to allocate space for spilling | 668 // we sync them with the actual frame to allocate space for spilling |
| 669 // them later. First sync everything above the stack pointer so we can | 669 // them later. First sync everything above the stack pointer so we can |
| 670 // use pushes to allocate and initialize the locals. | 670 // use pushes to allocate and initialize the locals. |
| 671 SyncRange(stack_pointer_ + 1, elements_.length()); | 671 SyncRange(stack_pointer_ + 1, elements_.length()); |
| 672 Handle<Object> undefined = Factory::undefined_value(); | 672 Handle<Object> undefined = Factory::undefined_value(); |
| 673 FrameElement initial_value(undefined, FrameElement::SYNCED); | 673 FrameElement initial_value = |
| 674 FrameElement::ConstantElement(undefined, FrameElement::SYNCED); |
| 674 Register temp = cgen_->allocator()->Allocate(); | 675 Register temp = cgen_->allocator()->Allocate(); |
| 675 __ Set(temp, Immediate(undefined)); | 676 __ Set(temp, Immediate(undefined)); |
| 676 for (int i = 0; i < count; i++) { | 677 for (int i = 0; i < count; i++) { |
| 677 elements_.Add(initial_value); | 678 elements_.Add(initial_value); |
| 678 stack_pointer_++; | 679 stack_pointer_++; |
| 679 __ push(temp); | 680 __ push(temp); |
| 680 } | 681 } |
| 681 cgen_->allocator()->Unuse(temp); | 682 cgen_->allocator()->Unuse(temp); |
| 682 } | 683 } |
| 683 } | 684 } |
| 684 | 685 |
| 685 | 686 |
| 686 void VirtualFrame::LoadFrameSlotAt(int index) { | 687 void VirtualFrame::LoadFrameSlotAt(int index) { |
| 687 ASSERT(index >= 0); | 688 ASSERT(index >= 0); |
| 688 ASSERT(index < elements_.length()); | 689 ASSERT(index < elements_.length()); |
| 689 | 690 |
| 690 FrameElement element = elements_[index]; | 691 FrameElement element = elements_[index]; |
| 691 | 692 |
| 692 if (element.is_memory()) { | 693 if (element.is_memory()) { |
| 693 ASSERT(index <= stack_pointer_); | 694 ASSERT(index <= stack_pointer_); |
| 694 // Eagerly load memory elements into a register. The element at | 695 // Eagerly load memory elements into a register. The element at |
| 695 // the index and the new top of the frame are backed by the same | 696 // the index and the new top of the frame are backed by the same |
| 696 // register location. | 697 // register location. |
| 697 Register temp = cgen_->allocator()->Allocate(); | 698 Register temp = cgen_->allocator()->Allocate(); |
| 698 ASSERT(!temp.is(no_reg)); | 699 ASSERT(!temp.is(no_reg)); |
| 699 FrameElement new_element(temp, FrameElement::NOT_SYNCED); | 700 FrameElement new_element |
| 701 = FrameElement::RegisterElement(temp, FrameElement::NOT_SYNCED); |
| 700 Use(temp); | 702 Use(temp); |
| 701 elements_[index] = new_element; | 703 elements_[index] = new_element; |
| 702 Use(temp); | 704 Use(temp); |
| 703 elements_.Add(new_element); | 705 elements_.Add(new_element); |
| 704 | 706 |
| 705 // Finally, move the element at the index into its new location. | 707 // Finally, move the element at the index into its new location. |
| 706 elements_[index].set_sync(); | 708 elements_[index].set_sync(); |
| 707 __ mov(temp, Operand(ebp, fp_relative(index))); | 709 __ mov(temp, Operand(ebp, fp_relative(index))); |
| 708 | 710 |
| 709 cgen_->allocator()->Unuse(temp); | 711 cgen_->allocator()->Unuse(temp); |
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 874 void VirtualFrame::EmitPop(Operand operand) { | 876 void VirtualFrame::EmitPop(Operand operand) { |
| 875 ASSERT(stack_pointer_ == elements_.length() - 1); | 877 ASSERT(stack_pointer_ == elements_.length() - 1); |
| 876 stack_pointer_--; | 878 stack_pointer_--; |
| 877 elements_.RemoveLast(); | 879 elements_.RemoveLast(); |
| 878 __ pop(operand); | 880 __ pop(operand); |
| 879 } | 881 } |
| 880 | 882 |
| 881 | 883 |
| 882 void VirtualFrame::EmitPush(Register reg) { | 884 void VirtualFrame::EmitPush(Register reg) { |
| 883 ASSERT(stack_pointer_ == elements_.length() - 1); | 885 ASSERT(stack_pointer_ == elements_.length() - 1); |
| 884 elements_.Add(FrameElement()); | 886 elements_.Add(FrameElement::MemoryElement()); |
| 885 stack_pointer_++; | 887 stack_pointer_++; |
| 886 __ push(reg); | 888 __ push(reg); |
| 887 } | 889 } |
| 888 | 890 |
| 889 | 891 |
| 890 void VirtualFrame::EmitPush(Operand operand) { | 892 void VirtualFrame::EmitPush(Operand operand) { |
| 891 ASSERT(stack_pointer_ == elements_.length() - 1); | 893 ASSERT(stack_pointer_ == elements_.length() - 1); |
| 892 elements_.Add(FrameElement()); | 894 elements_.Add(FrameElement::MemoryElement()); |
| 893 stack_pointer_++; | 895 stack_pointer_++; |
| 894 __ push(operand); | 896 __ push(operand); |
| 895 } | 897 } |
| 896 | 898 |
| 897 | 899 |
| 898 void VirtualFrame::EmitPush(Immediate immediate) { | 900 void VirtualFrame::EmitPush(Immediate immediate) { |
| 899 ASSERT(stack_pointer_ == elements_.length() - 1); | 901 ASSERT(stack_pointer_ == elements_.length() - 1); |
| 900 FrameElement memory_element; | 902 elements_.Add(FrameElement::MemoryElement()); |
| 901 elements_.Add(memory_element); | |
| 902 stack_pointer_++; | 903 stack_pointer_++; |
| 903 __ push(immediate); | 904 __ push(immediate); |
| 904 } | 905 } |
| 905 | 906 |
| 906 | 907 |
| 907 void VirtualFrame::Push(Register reg) { | 908 void VirtualFrame::Push(Register reg) { |
| 908 FrameElement register_element(reg, FrameElement::NOT_SYNCED); | |
| 909 Use(reg); | 909 Use(reg); |
| 910 elements_.Add(register_element); | 910 elements_.Add(FrameElement::RegisterElement(reg, |
| 911 FrameElement::NOT_SYNCED)); |
| 911 } | 912 } |
| 912 | 913 |
| 913 | 914 |
| 914 void VirtualFrame::Push(Handle<Object> value) { | 915 void VirtualFrame::Push(Handle<Object> value) { |
| 915 FrameElement constant_element(value, FrameElement::NOT_SYNCED); | 916 elements_.Add(FrameElement::ConstantElement(value, |
| 916 elements_.Add(constant_element); | 917 FrameElement::NOT_SYNCED)); |
| 917 } | 918 } |
| 918 | 919 |
| 919 | 920 |
| 920 #ifdef DEBUG | 921 #ifdef DEBUG |
| 921 bool VirtualFrame::IsSpilled() { | 922 bool VirtualFrame::IsSpilled() { |
| 922 for (int i = 0; i < elements_.length(); i++) { | 923 for (int i = 0; i < elements_.length(); i++) { |
| 923 if (!elements_[i].is_memory()) { | 924 if (!elements_[i].is_memory()) { |
| 924 return false; | 925 return false; |
| 925 } | 926 } |
| 926 } | 927 } |
| 927 return true; | 928 return true; |
| 928 } | 929 } |
| 929 #endif | 930 #endif |
| 930 | 931 |
| 931 #undef __ | 932 #undef __ |
| 932 | 933 |
| 933 } } // namespace v8::internal | 934 } } // namespace v8::internal |
| OLD | NEW |