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

Side by Side Diff: src/mips64/debug-mips64.cc

Issue 1234833003: Debugger: use debug break slots to break at function exit. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: fix for arm Created 5 years, 5 months 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
« no previous file with comments | « src/mips64/assembler-mips64-inl.h ('k') | src/mips64/full-codegen-mips64.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 5
6 6
7 #include "src/v8.h" 7 #include "src/v8.h"
8 8
9 #if V8_TARGET_ARCH_MIPS64 9 #if V8_TARGET_ARCH_MIPS64
10 10
11 #include "src/codegen.h" 11 #include "src/codegen.h"
12 #include "src/debug.h" 12 #include "src/debug.h"
13 13
14 namespace v8 { 14 namespace v8 {
15 namespace internal { 15 namespace internal {
16 16
17 void BreakLocation::SetDebugBreakAtReturn() { 17 #define __ ACCESS_MASM(masm)
18 // Mips return sequence:
19 // mov sp, fp
20 // lw fp, sp(0)
21 // lw ra, sp(4)
22 // addiu sp, sp, 8
23 // addiu sp, sp, N
24 // jr ra
25 // nop (in branch delay slot)
26 18
27 // Make sure this constant matches the number if instructions we emit. 19 void EmitDebugBreakSlot(MacroAssembler* masm) {
28 DCHECK(Assembler::kJSReturnSequenceInstructions == 7); 20 Label check_size;
29 CodePatcher patcher(pc(), Assembler::kJSReturnSequenceInstructions); 21 __ bind(&check_size);
30 // li and Call pseudo-instructions emit 6 + 2 instructions. 22 for (int i = 0; i < Assembler::kDebugBreakSlotInstructions; i++) {
31 patcher.masm()->li(v8::internal::t9, Operand(reinterpret_cast<int64_t>( 23 __ nop(MacroAssembler::DEBUG_BREAK_NOP);
32 debug_info_->GetIsolate()->builtins()->Return_DebugBreak()->entry())), 24 }
33 ADDRESS_LOAD); 25 DCHECK_EQ(Assembler::kDebugBreakSlotInstructions,
34 patcher.masm()->Call(v8::internal::t9); 26 masm->InstructionsGeneratedSince(&check_size));
35 // Place nop to match return sequence size.
36 patcher.masm()->nop();
37 // TODO(mips): Open issue about using breakpoint instruction instead of nops.
38 // patcher.masm()->bkpt(0);
39 } 27 }
40 28
41 29
42 void BreakLocation::SetDebugBreakAtSlot() { 30 void DebugCodegen::GenerateSlot(MacroAssembler* masm, RelocInfo::Mode mode,
43 DCHECK(IsDebugBreakSlot()); 31 int call_argc) {
32 // Generate enough nop's to make space for a call instruction. Avoid emitting
33 // the trampoline pool in the debug break slot code.
34 Assembler::BlockTrampolinePoolScope block_pool(masm);
35 masm->RecordDebugBreakSlot(mode, call_argc);
36 EmitDebugBreakSlot(masm);
37 }
38
39
40 void DebugCodegen::ClearDebugBreakSlot(Address pc) {
41 CodePatcher patcher(pc, Assembler::kDebugBreakSlotInstructions);
42 EmitDebugBreakSlot(patcher.masm());
43 }
44
45
46 void DebugCodegen::PatchDebugBreakSlot(Address pc, Handle<Code> code) {
47 DCHECK_EQ(Code::BUILTIN, code->kind());
48 CodePatcher patcher(pc, Assembler::kDebugBreakSlotInstructions);
44 // Patch the code changing the debug break slot code from: 49 // Patch the code changing the debug break slot code from:
45 // nop(DEBUG_BREAK_NOP) - nop(1) is sll(zero_reg, zero_reg, 1) 50 // nop(DEBUG_BREAK_NOP) - nop(1) is sll(zero_reg, zero_reg, 1)
46 // nop(DEBUG_BREAK_NOP) 51 // nop(DEBUG_BREAK_NOP)
47 // nop(DEBUG_BREAK_NOP) 52 // nop(DEBUG_BREAK_NOP)
48 // nop(DEBUG_BREAK_NOP) 53 // nop(DEBUG_BREAK_NOP)
49 // nop(DEBUG_BREAK_NOP) 54 // nop(DEBUG_BREAK_NOP)
50 // nop(DEBUG_BREAK_NOP) 55 // nop(DEBUG_BREAK_NOP)
51 // to a call to the debug break slot code. 56 // to a call to the debug break slot code.
52 // li t9, address (4-instruction sequence on mips64) 57 // li t9, address (4-instruction sequence on mips64)
53 // call t9 (jalr t9 / nop instruction pair) 58 // call t9 (jalr t9 / nop instruction pair)
54 CodePatcher patcher(pc(), Assembler::kDebugBreakSlotInstructions);
55 patcher.masm()->li(v8::internal::t9, 59 patcher.masm()->li(v8::internal::t9,
56 Operand(reinterpret_cast<int64_t>( 60 Operand(reinterpret_cast<int64_t>(code->entry())),
57 debug_info_->GetIsolate()->builtins()->Slot_DebugBreak()->entry())), 61 ADDRESS_LOAD);
58 ADDRESS_LOAD);
59 patcher.masm()->Call(v8::internal::t9); 62 patcher.masm()->Call(v8::internal::t9);
60 } 63 }
61 64
62 65
63 #define __ ACCESS_MASM(masm) 66 void DebugCodegen::GenerateDebugBreakStub(MacroAssembler* masm,
64 67 DebugBreakCallHelperMode mode) {
65 68 __ RecordComment("Debug break");
66 static void Generate_DebugBreakCallHelper(MacroAssembler* masm,
67 RegList object_regs) {
68 { 69 {
69 FrameScope scope(masm, StackFrame::INTERNAL); 70 FrameScope scope(masm, StackFrame::INTERNAL);
70 71
71 // Load padding words on stack. 72 // Load padding words on stack.
72 __ li(at, Operand(Smi::FromInt(LiveEdit::kFramePaddingValue))); 73 __ li(at, Operand(Smi::FromInt(LiveEdit::kFramePaddingValue)));
73 __ Dsubu(sp, sp, 74 __ Dsubu(sp, sp,
74 Operand(kPointerSize * LiveEdit::kFramePaddingInitialSize)); 75 Operand(kPointerSize * LiveEdit::kFramePaddingInitialSize));
75 for (int i = LiveEdit::kFramePaddingInitialSize - 1; i >= 0; i--) { 76 for (int i = LiveEdit::kFramePaddingInitialSize - 1; i >= 0; i--) {
76 __ sd(at, MemOperand(sp, kPointerSize * i)); 77 __ sd(at, MemOperand(sp, kPointerSize * i));
77 } 78 }
78 __ li(at, Operand(Smi::FromInt(LiveEdit::kFramePaddingInitialSize))); 79 __ li(at, Operand(Smi::FromInt(LiveEdit::kFramePaddingInitialSize)));
79 __ push(at); 80 __ push(at);
80 81
82 if (mode == SAVE_RESULT_REGISTER) __ push(v0);
81 83
82 // TODO(plind): This needs to be revised to store pairs of smi's per
83 // the other 64-bit arch's.
84
85 // Store the registers containing live values on the expression stack to
86 // make sure that these are correctly updated during GC. Non object values
87 // are stored as a smi causing it to be untouched by GC.
88 DCHECK((object_regs & ~kJSCallerSaved) == 0);
89 for (int i = 0; i < kNumJSCallerSaved; i++) {
90 int r = JSCallerSavedCode(i);
91 Register reg = { r };
92 if ((object_regs & (1 << r)) != 0) {
93 __ push(reg);
94 }
95 }
96
97 #ifdef DEBUG
98 __ RecordComment("// Calling from debug break to runtime - come in - over");
99 #endif
100 __ PrepareCEntryArgs(0); // No arguments. 84 __ PrepareCEntryArgs(0); // No arguments.
101 __ PrepareCEntryFunction(ExternalReference::debug_break(masm->isolate())); 85 __ PrepareCEntryFunction(ExternalReference::debug_break(masm->isolate()));
102 86
103 CEntryStub ceb(masm->isolate(), 1); 87 CEntryStub ceb(masm->isolate(), 1);
104 __ CallStub(&ceb); 88 __ CallStub(&ceb);
105 89
106 // Restore the register values from the expression stack. 90 if (FLAG_debug_code) {
107 for (int i = kNumJSCallerSaved - 1; i >= 0; i--) { 91 for (int i = 0; i < kNumJSCallerSaved; i++) {
108 int r = JSCallerSavedCode(i); 92 Register reg = {JSCallerSavedCode(i)};
109 Register reg = { r };
110 if ((object_regs & (1 << r)) != 0) {
111 __ pop(reg);
112 }
113 if (FLAG_debug_code && ((object_regs & (1 << r)) == 0)) {
114 __ li(reg, kDebugZapValue); 93 __ li(reg, kDebugZapValue);
115 } 94 }
116 } 95 }
117 96
97 if (mode == SAVE_RESULT_REGISTER) __ pop(v0);
98
118 // Don't bother removing padding bytes pushed on the stack 99 // Don't bother removing padding bytes pushed on the stack
119 // as the frame is going to be restored right away. 100 // as the frame is going to be restored right away.
120 101
121 // Leave the internal frame. 102 // Leave the internal frame.
122 } 103 }
123 104
124 // Now that the break point has been handled, resume normal execution by 105 // Now that the break point has been handled, resume normal execution by
125 // jumping to the target address intended by the caller and that was 106 // jumping to the target address intended by the caller and that was
126 // overwritten by the address of DebugBreakXXX. 107 // overwritten by the address of DebugBreakXXX.
127 ExternalReference after_break_target = 108 ExternalReference after_break_target =
128 ExternalReference::debug_after_break_target_address(masm->isolate()); 109 ExternalReference::debug_after_break_target_address(masm->isolate());
129 __ li(t9, Operand(after_break_target)); 110 __ li(t9, Operand(after_break_target));
130 __ ld(t9, MemOperand(t9)); 111 __ ld(t9, MemOperand(t9));
131 __ Jump(t9); 112 __ Jump(t9);
132 } 113 }
133 114
134 115
135 void DebugCodegen::GenerateReturnDebugBreak(MacroAssembler* masm) {
136 // In places other than IC call sites it is expected that v0 is TOS which
137 // is an object - this is not generally the case so this should be used with
138 // care.
139 Generate_DebugBreakCallHelper(masm, v0.bit());
140 }
141
142
143 void DebugCodegen::GenerateSlot(MacroAssembler* masm,
144 DebugCodegen::SlotLocation location,
145 int call_argc) {
146 // Generate enough nop's to make space for a call instruction. Avoid emitting
147 // the trampoline pool in the debug break slot code.
148 Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm);
149 Label check_codesize;
150 __ bind(&check_codesize);
151 RecordRelocInfo(masm, location, call_argc);
152 for (int i = 0; i < Assembler::kDebugBreakSlotInstructions; i++) {
153 __ nop(MacroAssembler::DEBUG_BREAK_NOP);
154 }
155 DCHECK_EQ(Assembler::kDebugBreakSlotInstructions,
156 masm->InstructionsGeneratedSince(&check_codesize));
157 }
158
159
160 void DebugCodegen::GenerateSlotDebugBreak(MacroAssembler* masm) {
161 // In the places where a debug break slot is inserted no registers can contain
162 // object pointers.
163 Generate_DebugBreakCallHelper(masm, 0);
164 }
165
166
167 void DebugCodegen::GeneratePlainReturnLiveEdit(MacroAssembler* masm) { 116 void DebugCodegen::GeneratePlainReturnLiveEdit(MacroAssembler* masm) {
168 __ Ret(); 117 __ Ret();
169 } 118 }
170 119
171 120
172 void DebugCodegen::GenerateFrameDropperLiveEdit(MacroAssembler* masm) { 121 void DebugCodegen::GenerateFrameDropperLiveEdit(MacroAssembler* masm) {
173 ExternalReference restarter_frame_function_slot = 122 ExternalReference restarter_frame_function_slot =
174 ExternalReference::debug_restarter_frame_function_pointer_address( 123 ExternalReference::debug_restarter_frame_function_pointer_address(
175 masm->isolate()); 124 masm->isolate());
176 __ li(at, Operand(restarter_frame_function_slot)); 125 __ li(at, Operand(restarter_frame_function_slot));
(...skipping 18 matching lines...) Expand all
195 144
196 145
197 const bool LiveEdit::kFrameDropperSupported = true; 146 const bool LiveEdit::kFrameDropperSupported = true;
198 147
199 #undef __ 148 #undef __
200 149
201 } // namespace internal 150 } // namespace internal
202 } // namespace v8 151 } // namespace v8
203 152
204 #endif // V8_TARGET_ARCH_MIPS64 153 #endif // V8_TARGET_ARCH_MIPS64
OLDNEW
« no previous file with comments | « src/mips64/assembler-mips64-inl.h ('k') | src/mips64/full-codegen-mips64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698