Index: src/x64/virtual-frame-x64.cc |
=================================================================== |
--- src/x64/virtual-frame-x64.cc (revision 2145) |
+++ src/x64/virtual-frame-x64.cc (working copy) |
@@ -25,3 +25,170 @@ |
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
+#include "v8.h" |
+ |
+#include "codegen-inl.h" |
+#include "register-allocator-inl.h" |
+#include "scopes.h" |
+ |
+namespace v8 { |
+namespace internal { |
+ |
+#define __ ACCESS_MASM(masm()) |
+ |
+// ------------------------------------------------------------------------- |
+// VirtualFrame implementation. |
+ |
+// On entry to a function, the virtual frame already contains the receiver, |
+// the parameters, and a return address. All frame elements are in memory. |
+VirtualFrame::VirtualFrame() |
+ : elements_(parameter_count() + local_count() + kPreallocatedElements), |
+ stack_pointer_(parameter_count() + 1) { // 0-based index of TOS. |
+ for (int i = 0; i <= stack_pointer_; i++) { |
+ elements_.Add(FrameElement::MemoryElement()); |
+ } |
+ for (int i = 0; i < RegisterAllocator::kNumRegisters; i++) { |
+ register_locations_[i] = kIllegalIndex; |
+ } |
+} |
+ |
+ |
+void VirtualFrame::Enter() { |
+ // Registers live on entry to a JS frame: |
+ // rsp: stack pointer, points to return address from this function. |
+ // rbp: base pointer, points to previous JS, ArgumentsAdaptor, or |
+ // Trampoline frame. |
+ // rsi: context of this function call. |
+ // rdi: pointer to this function object. |
+ Comment cmnt(masm(), "[ Enter JS frame"); |
+ |
+#ifdef DEBUG |
+ // Verify that rdi contains a JS function. The following code |
+ // relies on rax being available for use. |
+ __ testq(rdi, Immediate(kSmiTagMask)); |
+ __ Check(not_zero, |
+ "VirtualFrame::Enter - rdi is not a function (smi check)."); |
+ __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rax); |
+ __ Check(equal, |
+ "VirtualFrame::Enter - rdi is not a function (map check)."); |
+#endif |
+ |
+ EmitPush(rbp); |
+ |
+ __ movq(rbp, rsp); |
+ |
+ // Store the context in the frame. The context is kept in rsi and a |
+ // copy is stored in the frame. The external reference to rsi |
+ // remains. |
+ EmitPush(rsi); |
+ |
+ // Store the function in the frame. The frame owns the register |
+ // reference now (ie, it can keep it in rdi or spill it later). |
+ Push(rdi); |
+ // SyncElementAt(element_count() - 1); |
+ cgen()->allocator()->Unuse(rdi); |
+} |
+ |
+ |
+void VirtualFrame::Exit() { |
+ Comment cmnt(masm(), "[ Exit JS frame"); |
+ // Record the location of the JS exit code for patching when setting |
+ // break point. |
+ __ RecordJSReturn(); |
+ |
+ // Avoid using the leave instruction here, because it is too |
+ // short. We need the return sequence to be a least the size of a |
+ // call instruction to support patching the exit code in the |
+ // debugger. See VisitReturnStatement for the full return sequence. |
+ __ movq(rsp, rbp); |
+ stack_pointer_ = frame_pointer(); |
+ for (int i = element_count() - 1; i > stack_pointer_; i--) { |
+ FrameElement last = elements_.RemoveLast(); |
+ if (last.is_register()) { |
+ Unuse(last.reg()); |
+ } |
+ } |
+ |
+ EmitPop(rbp); |
+} |
+ |
+ |
+void VirtualFrame::EmitPop(Register reg) { |
+ ASSERT(stack_pointer_ == element_count() - 1); |
+ stack_pointer_--; |
+ elements_.RemoveLast(); |
+ __ pop(reg); |
+} |
+ |
+ |
+void VirtualFrame::EmitPop(const Operand& operand) { |
+ ASSERT(stack_pointer_ == element_count() - 1); |
+ stack_pointer_--; |
+ elements_.RemoveLast(); |
+ __ pop(operand); |
+} |
+ |
+ |
+void VirtualFrame::EmitPush(Register reg) { |
+ ASSERT(stack_pointer_ == element_count() - 1); |
+ elements_.Add(FrameElement::MemoryElement()); |
+ stack_pointer_++; |
+ __ push(reg); |
+} |
+ |
+ |
+void VirtualFrame::EmitPush(const Operand& operand) { |
+ ASSERT(stack_pointer_ == element_count() - 1); |
+ elements_.Add(FrameElement::MemoryElement()); |
+ stack_pointer_++; |
+ __ push(operand); |
+} |
+ |
+ |
+void VirtualFrame::EmitPush(Immediate immediate) { |
+ ASSERT(stack_pointer_ == element_count() - 1); |
+ elements_.Add(FrameElement::MemoryElement()); |
+ stack_pointer_++; |
+ __ push(immediate); |
+} |
+ |
+ |
+void VirtualFrame::Drop(int a) { |
+ UNIMPLEMENTED(); |
+} |
+ |
+int VirtualFrame::InvalidateFrameSlotAt(int a) { |
+ UNIMPLEMENTED(); |
+ return -1; |
+} |
+ |
+void VirtualFrame::MergeTo(VirtualFrame* a) { |
+ UNIMPLEMENTED(); |
+} |
+ |
+Result VirtualFrame::Pop() { |
+ UNIMPLEMENTED(); |
+ return Result(NULL); |
+} |
+ |
+Result VirtualFrame::RawCallStub(CodeStub* a) { |
+ UNIMPLEMENTED(); |
+ return Result(NULL); |
+} |
+ |
+void VirtualFrame::SyncElementBelowStackPointer(int a) { |
+ UNIMPLEMENTED(); |
+} |
+ |
+void VirtualFrame::SyncElementByPushing(int a) { |
+ UNIMPLEMENTED(); |
+} |
+ |
+void VirtualFrame::SyncRange(int a, int b) { |
+ UNIMPLEMENTED(); |
+} |
+ |
+ |
+#undef __ |
+ |
+} } // namespace v8::internal |