Line data Source code
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 :
20 4636800 : void EmitDebugBreakSlot(MacroAssembler* masm) {
21 : Label check_codesize;
22 4636800 : __ bind(&check_codesize);
23 4636800 : __ Nop(Assembler::kDebugBreakSlotLength);
24 : DCHECK_EQ(Assembler::kDebugBreakSlotLength,
25 : masm->SizeOfCodeGeneratedSince(&check_codesize));
26 4636800 : }
27 :
28 :
29 17028 : void DebugCodegen::GenerateSlot(MacroAssembler* masm, RelocInfo::Mode mode) {
30 : // Generate enough nop's to make space for a call instruction.
31 17028 : masm->RecordDebugBreakSlot(mode);
32 17028 : EmitDebugBreakSlot(masm);
33 17028 : }
34 :
35 :
36 4619772 : void DebugCodegen::ClearDebugBreakSlot(Isolate* isolate, Address pc) {
37 4619772 : CodePatcher patcher(isolate, pc, Assembler::kDebugBreakSlotLength);
38 4619772 : EmitDebugBreakSlot(patcher.masm());
39 4619772 : }
40 :
41 :
42 2212169 : 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 2212169 : CodePatcher patcher(isolate, pc, kSize);
47 : Label check_codesize;
48 2212169 : patcher.masm()->bind(&check_codesize);
49 2212169 : patcher.masm()->movp(kScratchRegister, reinterpret_cast<void*>(code->entry()),
50 2212169 : Assembler::RelocInfoNone());
51 2212169 : patcher.masm()->call(kScratchRegister);
52 : // Check that the size of the code generated is as expected.
53 2212169 : DCHECK_EQ(kSize, patcher.masm()->SizeOfCodeGeneratedSince(&check_codesize));
54 2212169 : }
55 :
56 87516 : bool DebugCodegen::DebugBreakSlotIsPatched(Address pc) {
57 87516 : return !Assembler::IsNop(pc);
58 : }
59 :
60 129 : void DebugCodegen::GenerateDebugBreakStub(MacroAssembler* masm,
61 : DebugBreakCallHelperMode mode) {
62 86 : __ RecordComment("Debug break");
63 :
64 : // Enter an internal frame.
65 : {
66 86 : FrameScope scope(masm, StackFrame::INTERNAL);
67 :
68 : // Push arguments for DebugBreak call.
69 86 : if (mode == SAVE_RESULT_REGISTER) {
70 : // Break on return.
71 43 : __ Push(rax);
72 : } else {
73 : // Non-return breaks.
74 43 : __ Push(masm->isolate()->factory()->the_hole_value());
75 : }
76 :
77 : __ CallRuntime(Runtime::kDebugBreak, 1, kDontSaveFPRegs);
78 :
79 86 : if (FLAG_debug_code) {
80 0 : for (int i = 0; i < kNumJSCallerSaved; ++i) {
81 0 : 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 0 : if (!(reg.is(rax) && (mode == SAVE_RESULT_REGISTER))) {
85 0 : __ Set(reg, kDebugZapValue);
86 : }
87 : }
88 86 : }
89 : // Get rid of the internal frame.
90 : }
91 :
92 86 : __ MaybeDropFrames();
93 :
94 : // Return to caller.
95 86 : __ ret(0);
96 86 : }
97 :
98 43 : void DebugCodegen::GenerateHandleDebuggerStatement(MacroAssembler* masm) {
99 : {
100 43 : FrameScope scope(masm, StackFrame::INTERNAL);
101 43 : __ CallRuntime(Runtime::kHandleDebuggerStatement, 0);
102 : }
103 43 : __ MaybeDropFrames();
104 :
105 : // Return to caller.
106 43 : __ ret(0);
107 43 : }
108 :
109 43 : 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 43 : __ movp(rbp, rbx);
116 86 : __ movp(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
117 43 : __ leave();
118 :
119 : __ movp(rbx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
120 : __ LoadSharedFunctionInfoSpecialField(
121 43 : rbx, rbx, SharedFunctionInfo::kFormalParameterCountOffset);
122 :
123 : ParameterCount dummy(rbx);
124 : __ InvokeFunction(rdi, no_reg, dummy, dummy, JUMP_FUNCTION,
125 43 : CheckDebugStepCallWrapper());
126 43 : }
127 :
128 : const bool LiveEdit::kFrameDropperSupported = true;
129 :
130 : #undef __
131 :
132 : } // namespace internal
133 : } // namespace v8
134 :
135 : #endif // V8_TARGET_ARCH_X64
|