• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #if V8_TARGET_ARCH_X64
6 
7 #include "src/debug/debug.h"
8 
9 #include "src/assembler.h"
10 #include "src/codegen.h"
11 #include "src/debug/liveedit.h"
12 #include "src/objects-inl.h"
13 
14 namespace v8 {
15 namespace internal {
16 
17 #define __ ACCESS_MASM(masm)
18 
19 
EmitDebugBreakSlot(MacroAssembler * masm)20 void EmitDebugBreakSlot(MacroAssembler* masm) {
21   Label check_codesize;
22   __ bind(&check_codesize);
23   __ Nop(Assembler::kDebugBreakSlotLength);
24   DCHECK_EQ(Assembler::kDebugBreakSlotLength,
25             masm->SizeOfCodeGeneratedSince(&check_codesize));
26 }
27 
28 
GenerateSlot(MacroAssembler * masm,RelocInfo::Mode mode)29 void DebugCodegen::GenerateSlot(MacroAssembler* masm, RelocInfo::Mode mode) {
30   // Generate enough nop's to make space for a call instruction.
31   masm->RecordDebugBreakSlot(mode);
32   EmitDebugBreakSlot(masm);
33 }
34 
35 
ClearDebugBreakSlot(Isolate * isolate,Address pc)36 void DebugCodegen::ClearDebugBreakSlot(Isolate* isolate, Address pc) {
37   CodePatcher patcher(isolate, pc, Assembler::kDebugBreakSlotLength);
38   EmitDebugBreakSlot(patcher.masm());
39 }
40 
41 
PatchDebugBreakSlot(Isolate * isolate,Address pc,Handle<Code> code)42 void DebugCodegen::PatchDebugBreakSlot(Isolate* isolate, Address pc,
43                                        Handle<Code> code) {
44   DCHECK(code->is_debug_stub());
45   static const int kSize = Assembler::kDebugBreakSlotLength;
46   CodePatcher patcher(isolate, pc, kSize);
47   Label check_codesize;
48   patcher.masm()->bind(&check_codesize);
49   patcher.masm()->movp(kScratchRegister, reinterpret_cast<void*>(code->entry()),
50                        Assembler::RelocInfoNone());
51   patcher.masm()->call(kScratchRegister);
52   // Check that the size of the code generated is as expected.
53   DCHECK_EQ(kSize, patcher.masm()->SizeOfCodeGeneratedSince(&check_codesize));
54 }
55 
DebugBreakSlotIsPatched(Address pc)56 bool DebugCodegen::DebugBreakSlotIsPatched(Address pc) {
57   return !Assembler::IsNop(pc);
58 }
59 
GenerateDebugBreakStub(MacroAssembler * masm,DebugBreakCallHelperMode mode)60 void DebugCodegen::GenerateDebugBreakStub(MacroAssembler* masm,
61                                           DebugBreakCallHelperMode mode) {
62   __ RecordComment("Debug break");
63 
64   // Enter an internal frame.
65   {
66     FrameScope scope(masm, StackFrame::INTERNAL);
67 
68     // Push arguments for DebugBreak call.
69     if (mode == SAVE_RESULT_REGISTER) {
70       // Break on return.
71       __ Push(rax);
72     } else {
73       // Non-return breaks.
74       __ Push(masm->isolate()->factory()->the_hole_value());
75     }
76 
77     __ CallRuntime(Runtime::kDebugBreak, 1, kDontSaveFPRegs);
78 
79     if (FLAG_debug_code) {
80       for (int i = 0; i < kNumJSCallerSaved; ++i) {
81         Register reg = {JSCallerSavedCode(i)};
82         // Do not clobber rax if mode is SAVE_RESULT_REGISTER. It will
83         // contain return value of the function.
84         if (!(reg.is(rax) && (mode == SAVE_RESULT_REGISTER))) {
85           __ Set(reg, kDebugZapValue);
86         }
87       }
88     }
89     // Get rid of the internal frame.
90   }
91 
92   __ MaybeDropFrames();
93 
94   // Return to caller.
95   __ ret(0);
96 }
97 
GenerateHandleDebuggerStatement(MacroAssembler * masm)98 void DebugCodegen::GenerateHandleDebuggerStatement(MacroAssembler* masm) {
99   {
100     FrameScope scope(masm, StackFrame::INTERNAL);
101     __ CallRuntime(Runtime::kHandleDebuggerStatement, 0);
102   }
103   __ MaybeDropFrames();
104 
105   // Return to caller.
106   __ ret(0);
107 }
108 
GenerateFrameDropperTrampoline(MacroAssembler * masm)109 void DebugCodegen::GenerateFrameDropperTrampoline(MacroAssembler* masm) {
110   // Frame is being dropped:
111   // - Drop to the target frame specified by rbx.
112   // - Look up current function on the frame.
113   // - Leave the frame.
114   // - Restart the frame by calling the function.
115   __ movp(rbp, rbx);
116   __ movp(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
117   __ leave();
118 
119   __ movp(rbx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
120   __ LoadSharedFunctionInfoSpecialField(
121       rbx, rbx, SharedFunctionInfo::kFormalParameterCountOffset);
122 
123   ParameterCount dummy(rbx);
124   __ InvokeFunction(rdi, no_reg, dummy, dummy, JUMP_FUNCTION,
125                     CheckDebugStepCallWrapper());
126 }
127 
128 const bool LiveEdit::kFrameDropperSupported = true;
129 
130 #undef __
131 
132 }  // namespace internal
133 }  // namespace v8
134 
135 #endif  // V8_TARGET_ARCH_X64
136