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

Side by Side Diff: src/arm/debug-arm.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/arm/assembler-arm-inl.h ('k') | src/arm/full-codegen-arm.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 #include "src/v8.h" 5 #include "src/v8.h"
6 6
7 #if V8_TARGET_ARCH_ARM 7 #if V8_TARGET_ARCH_ARM
8 8
9 #include "src/codegen.h" 9 #include "src/codegen.h"
10 #include "src/debug.h" 10 #include "src/debug.h"
11 11
12 namespace v8 { 12 namespace v8 {
13 namespace internal { 13 namespace internal {
14 14
15 void BreakLocation::SetDebugBreakAtReturn() { 15 #define __ ACCESS_MASM(masm)
16 // Patch the code changing the return from JS function sequence from 16
17 // mov sp, fp 17
18 // ldmia sp!, {fp, lr} 18 void EmitDebugBreakSlot(MacroAssembler* masm) {
19 // add sp, sp, #4 19 Label check_size;
20 // bx lr 20 __ bind(&check_size);
21 // to a call to the debug break return code. 21 for (int i = 0; i < Assembler::kDebugBreakSlotInstructions; i++) {
22 // ldr ip, [pc, #0] 22 __ nop(MacroAssembler::DEBUG_BREAK_NOP);
23 // blx ip 23 }
24 // <debug break return code entry point address> 24 DCHECK_EQ(Assembler::kDebugBreakSlotInstructions,
25 // bkpt 0 25 masm->InstructionsGeneratedSince(&check_size));
26 CodePatcher patcher(pc(), Assembler::kJSReturnSequenceInstructions);
27 patcher.masm()->ldr(v8::internal::ip, MemOperand(v8::internal::pc, 0));
28 patcher.masm()->blx(v8::internal::ip);
29 patcher.Emit(
30 debug_info_->GetIsolate()->builtins()->Return_DebugBreak()->entry());
31 patcher.masm()->bkpt(0);
32 } 26 }
33 27
34 28
35 void BreakLocation::SetDebugBreakAtSlot() { 29 void DebugCodegen::GenerateSlot(MacroAssembler* masm, RelocInfo::Mode mode,
36 DCHECK(IsDebugBreakSlot()); 30 int call_argc) {
31 // Generate enough nop's to make space for a call instruction. Avoid emitting
32 // the constant pool in the debug break slot code.
33 Assembler::BlockConstPoolScope block_const_pool(masm);
34 masm->RecordDebugBreakSlot(mode, call_argc);
35 EmitDebugBreakSlot(masm);
36 }
37
38
39 void DebugCodegen::ClearDebugBreakSlot(Address pc) {
40 CodePatcher patcher(pc, Assembler::kDebugBreakSlotInstructions);
41 EmitDebugBreakSlot(patcher.masm());
42 }
43
44
45 void DebugCodegen::PatchDebugBreakSlot(Address pc, Handle<Code> code) {
46 DCHECK_EQ(Code::BUILTIN, code->kind());
47 CodePatcher patcher(pc, Assembler::kDebugBreakSlotInstructions);
37 // Patch the code changing the debug break slot code from 48 // Patch the code changing the debug break slot code from
38 // mov r2, r2 49 // mov r2, r2
39 // mov r2, r2 50 // mov r2, r2
40 // mov r2, r2 51 // mov r2, r2
52 // mov r2, r2
41 // to a call to the debug break slot code. 53 // to a call to the debug break slot code.
42 // ldr ip, [pc, #0] 54 // ldr ip, [pc, #0]
55 // b skip
56 // <debug break slot code entry point address>
57 // skip:
43 // blx ip 58 // blx ip
44 // <debug break slot code entry point address> 59 Label skip_constant;
45 CodePatcher patcher(pc(), Assembler::kDebugBreakSlotInstructions); 60 patcher.masm()->ldr(ip, MemOperand(v8::internal::pc, 0));
46 patcher.masm()->ldr(v8::internal::ip, MemOperand(v8::internal::pc, 0)); 61 patcher.masm()->b(&skip_constant);
47 patcher.masm()->blx(v8::internal::ip); 62 patcher.Emit(code->entry());
48 patcher.Emit( 63 patcher.masm()->bind(&skip_constant);
49 debug_info_->GetIsolate()->builtins()->Slot_DebugBreak()->entry()); 64 patcher.masm()->blx(ip);
50 } 65 }
51 66
52 67
53 #define __ ACCESS_MASM(masm) 68 void DebugCodegen::GenerateDebugBreakStub(MacroAssembler* masm,
54 69 DebugBreakCallHelperMode mode) {
55 70 __ RecordComment("Debug break");
56 static void Generate_DebugBreakCallHelper(MacroAssembler* masm,
57 RegList object_regs) {
58 { 71 {
59 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); 72 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
60 73
61 // Load padding words on stack. 74 // Load padding words on stack.
62 __ mov(ip, Operand(Smi::FromInt(LiveEdit::kFramePaddingValue))); 75 __ mov(ip, Operand(Smi::FromInt(LiveEdit::kFramePaddingValue)));
63 for (int i = 0; i < LiveEdit::kFramePaddingInitialSize; i++) { 76 for (int i = 0; i < LiveEdit::kFramePaddingInitialSize; i++) {
64 __ push(ip); 77 __ push(ip);
65 } 78 }
66 __ mov(ip, Operand(Smi::FromInt(LiveEdit::kFramePaddingInitialSize))); 79 __ mov(ip, Operand(Smi::FromInt(LiveEdit::kFramePaddingInitialSize)));
67 __ push(ip); 80 __ push(ip);
68 81
69 // Store the registers containing live values on the expression stack to 82 if (mode == SAVE_RESULT_REGISTER) __ push(r0);
70 // make sure that these are correctly updated during GC. Non object values
71 // are stored as a smi causing it to be untouched by GC.
72 DCHECK((object_regs & ~kJSCallerSaved) == 0);
73 if (object_regs != 0) {
74 __ stm(db_w, sp, object_regs);
75 }
76 83
77 #ifdef DEBUG
78 __ RecordComment("// Calling from debug break to runtime - come in - over");
79 #endif
80 __ mov(r0, Operand::Zero()); // no arguments 84 __ mov(r0, Operand::Zero()); // no arguments
81 __ mov(r1, Operand(ExternalReference::debug_break(masm->isolate()))); 85 __ mov(r1, Operand(ExternalReference::debug_break(masm->isolate())));
82 86
83 CEntryStub ceb(masm->isolate(), 1); 87 CEntryStub ceb(masm->isolate(), 1);
84 __ CallStub(&ceb); 88 __ CallStub(&ceb);
85 89
86 // Restore the register values from the expression stack. 90 if (FLAG_debug_code) {
87 if (object_regs != 0) { 91 for (int i = 0; i < kNumJSCallerSaved; i++) {
88 __ ldm(ia_w, sp, object_regs); 92 Register reg = {JSCallerSavedCode(i)};
89 }
90
91 for (int i = 0; i < kNumJSCallerSaved; i++) {
92 int r = JSCallerSavedCode(i);
93 Register reg = {r};
94 if (FLAG_debug_code && ((object_regs & (1 << r)) == 0)) {
95 __ mov(reg, Operand(kDebugZapValue)); 93 __ mov(reg, Operand(kDebugZapValue));
96 } 94 }
97 } 95 }
98 96
97 if (mode == SAVE_RESULT_REGISTER) __ pop(r0);
98
99 // Don't bother removing padding bytes pushed on the stack 99 // Don't bother removing padding bytes pushed on the stack
100 // as the frame is going to be restored right away. 100 // as the frame is going to be restored right away.
101 101
102 // Leave the internal frame. 102 // Leave the internal frame.
103 } 103 }
104 104
105 // 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
106 // 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
107 // overwritten by the address of DebugBreakXXX. 107 // overwritten by the address of DebugBreakXXX.
108 ExternalReference after_break_target = 108 ExternalReference after_break_target =
109 ExternalReference::debug_after_break_target_address(masm->isolate()); 109 ExternalReference::debug_after_break_target_address(masm->isolate());
110 __ mov(ip, Operand(after_break_target)); 110 __ mov(ip, Operand(after_break_target));
111 __ ldr(ip, MemOperand(ip)); 111 __ ldr(ip, MemOperand(ip));
112 __ Jump(ip); 112 __ Jump(ip);
113 } 113 }
114 114
115 115
116 void DebugCodegen::GenerateReturnDebugBreak(MacroAssembler* masm) {
117 // In places other than IC call sites it is expected that r0 is TOS which
118 // is an object - this is not generally the case so this should be used with
119 // care.
120 Generate_DebugBreakCallHelper(masm, r0.bit());
121 }
122
123
124 void DebugCodegen::GenerateSlot(MacroAssembler* masm,
125 DebugCodegen::SlotLocation location,
126 int call_argc) {
127 // Generate enough nop's to make space for a call instruction. Avoid emitting
128 // the constant pool in the debug break slot code.
129 Assembler::BlockConstPoolScope block_const_pool(masm);
130 Label check_codesize;
131 __ bind(&check_codesize);
132 RecordRelocInfo(masm, location, call_argc);
133 for (int i = 0; i < Assembler::kDebugBreakSlotInstructions; i++) {
134 __ nop(MacroAssembler::DEBUG_BREAK_NOP);
135 }
136 DCHECK_EQ(Assembler::kDebugBreakSlotInstructions,
137 masm->InstructionsGeneratedSince(&check_codesize));
138 }
139
140
141 void DebugCodegen::GenerateSlotDebugBreak(MacroAssembler* masm) {
142 // In the places where a debug break slot is inserted no registers can contain
143 // object pointers.
144 Generate_DebugBreakCallHelper(masm, 0);
145 }
146
147
148 void DebugCodegen::GeneratePlainReturnLiveEdit(MacroAssembler* masm) { 116 void DebugCodegen::GeneratePlainReturnLiveEdit(MacroAssembler* masm) {
149 __ Ret(); 117 __ Ret();
150 } 118 }
151 119
152 120
153 void DebugCodegen::GenerateFrameDropperLiveEdit(MacroAssembler* masm) { 121 void DebugCodegen::GenerateFrameDropperLiveEdit(MacroAssembler* masm) {
154 ExternalReference restarter_frame_function_slot = 122 ExternalReference restarter_frame_function_slot =
155 ExternalReference::debug_restarter_frame_function_pointer_address( 123 ExternalReference::debug_restarter_frame_function_pointer_address(
156 masm->isolate()); 124 masm->isolate());
157 __ mov(ip, Operand(restarter_frame_function_slot)); 125 __ mov(ip, Operand(restarter_frame_function_slot));
(...skipping 24 matching lines...) Expand all
182 150
183 151
184 const bool LiveEdit::kFrameDropperSupported = true; 152 const bool LiveEdit::kFrameDropperSupported = true;
185 153
186 #undef __ 154 #undef __
187 155
188 } // namespace internal 156 } // namespace internal
189 } // namespace v8 157 } // namespace v8
190 158
191 #endif // V8_TARGET_ARCH_ARM 159 #endif // V8_TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « src/arm/assembler-arm-inl.h ('k') | src/arm/full-codegen-arm.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698