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

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

Issue 1222093007: Debugger: use debug break slot to break on call. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: rebased and addressed comments 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/ia32/assembler-ia32.h ('k') | src/ia32/full-codegen-ia32.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_IA32 7 #if V8_TARGET_ARCH_IA32
8 8
9 #include "src/codegen.h" 9 #include "src/codegen.h"
10 #include "src/debug.h" 10 #include "src/debug.h"
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
64 Isolate* isolate = debug_info_->GetIsolate(); 64 Isolate* isolate = debug_info_->GetIsolate();
65 PatchCodeWithCall( 65 PatchCodeWithCall(
66 pc(), isolate->builtins()->Slot_DebugBreak()->entry(), 66 pc(), isolate->builtins()->Slot_DebugBreak()->entry(),
67 Assembler::kDebugBreakSlotLength - Assembler::kCallInstructionLength); 67 Assembler::kDebugBreakSlotLength - Assembler::kCallInstructionLength);
68 } 68 }
69 69
70 70
71 #define __ ACCESS_MASM(masm) 71 #define __ ACCESS_MASM(masm)
72 72
73 static void Generate_DebugBreakCallHelper(MacroAssembler* masm, 73 static void Generate_DebugBreakCallHelper(MacroAssembler* masm,
74 RegList object_regs, 74 RegList object_regs) {
75 RegList non_object_regs,
76 bool convert_call_to_jmp) {
77 // Enter an internal frame. 75 // Enter an internal frame.
78 { 76 {
79 FrameScope scope(masm, StackFrame::INTERNAL); 77 FrameScope scope(masm, StackFrame::INTERNAL);
80 78
81 // Load padding words on stack. 79 // Load padding words on stack.
82 for (int i = 0; i < LiveEdit::kFramePaddingInitialSize; i++) { 80 for (int i = 0; i < LiveEdit::kFramePaddingInitialSize; i++) {
83 __ push(Immediate(Smi::FromInt(LiveEdit::kFramePaddingValue))); 81 __ push(Immediate(Smi::FromInt(LiveEdit::kFramePaddingValue)));
84 } 82 }
85 __ push(Immediate(Smi::FromInt(LiveEdit::kFramePaddingInitialSize))); 83 __ push(Immediate(Smi::FromInt(LiveEdit::kFramePaddingInitialSize)));
86 84
87 // Store the registers containing live values on the expression stack to 85 // Store the registers containing live values on the expression stack to
88 // make sure that these are correctly updated during GC. Non object values 86 // make sure that these are correctly updated during GC. Non object values
89 // are stored as a smi causing it to be untouched by GC. 87 // are stored as a smi causing it to be untouched by GC.
90 DCHECK((object_regs & ~kJSCallerSaved) == 0); 88 DCHECK((object_regs & ~kJSCallerSaved) == 0);
91 DCHECK((non_object_regs & ~kJSCallerSaved) == 0);
92 DCHECK((object_regs & non_object_regs) == 0);
93 for (int i = 0; i < kNumJSCallerSaved; i++) { 89 for (int i = 0; i < kNumJSCallerSaved; i++) {
94 int r = JSCallerSavedCode(i); 90 int r = JSCallerSavedCode(i);
95 Register reg = { r }; 91 Register reg = { r };
96 if ((object_regs & (1 << r)) != 0) { 92 if ((object_regs & (1 << r)) != 0) {
97 __ push(reg); 93 __ push(reg);
98 } 94 }
99 if ((non_object_regs & (1 << r)) != 0) {
100 if (FLAG_debug_code) {
101 __ test(reg, Immediate(0xc0000000));
102 __ Assert(zero, kUnableToEncodeValueAsSmi);
103 }
104 __ SmiTag(reg);
105 __ push(reg);
106 }
107 } 95 }
108 96
109 #ifdef DEBUG 97 #ifdef DEBUG
110 __ RecordComment("// Calling from debug break to runtime - come in - over"); 98 __ RecordComment("// Calling from debug break to runtime - come in - over");
111 #endif 99 #endif
112 __ Move(eax, Immediate(0)); // No arguments. 100 __ Move(eax, Immediate(0)); // No arguments.
113 __ mov(ebx, Immediate(ExternalReference::debug_break(masm->isolate()))); 101 __ mov(ebx, Immediate(ExternalReference::debug_break(masm->isolate())));
114 102
115 CEntryStub ceb(masm->isolate(), 1); 103 CEntryStub ceb(masm->isolate(), 1);
116 __ CallStub(&ceb); 104 __ CallStub(&ceb);
117 105
118 // Automatically find register that could be used after register restore. 106 // Automatically find register that could be used after register restore.
119 // We need one register for padding skip instructions. 107 // We need one register for padding skip instructions.
120 Register unused_reg = { -1 }; 108 Register unused_reg = { -1 };
121 109
122 // Restore the register values containing object pointers from the 110 // Restore the register values containing object pointers from the
123 // expression stack. 111 // expression stack.
124 for (int i = kNumJSCallerSaved; --i >= 0;) { 112 for (int i = kNumJSCallerSaved; --i >= 0;) {
125 int r = JSCallerSavedCode(i); 113 int r = JSCallerSavedCode(i);
126 Register reg = { r }; 114 Register reg = { r };
127 if (FLAG_debug_code) { 115 if (FLAG_debug_code) {
128 __ Move(reg, Immediate(kDebugZapValue)); 116 __ Move(reg, Immediate(kDebugZapValue));
129 } 117 }
130 bool taken = reg.code() == esi.code(); 118 bool taken = reg.code() == esi.code();
131 if ((object_regs & (1 << r)) != 0) { 119 if ((object_regs & (1 << r)) != 0) {
132 __ pop(reg); 120 __ pop(reg);
133 taken = true; 121 taken = true;
134 } 122 }
135 if ((non_object_regs & (1 << r)) != 0) {
136 __ pop(reg);
137 __ SmiUntag(reg);
138 taken = true;
139 }
140 if (!taken) { 123 if (!taken) {
141 unused_reg = reg; 124 unused_reg = reg;
142 } 125 }
143 } 126 }
144 127
145 DCHECK(unused_reg.code() != -1); 128 DCHECK(unused_reg.code() != -1);
146 129
147 // Read current padding counter and skip corresponding number of words. 130 // Read current padding counter and skip corresponding number of words.
148 __ pop(unused_reg); 131 __ pop(unused_reg);
149 // We divide stored value by 2 (untagging) and multiply it by word's size. 132 // We divide stored value by 2 (untagging) and multiply it by word's size.
150 STATIC_ASSERT(kSmiTagSize == 1 && kSmiShiftSize == 0); 133 STATIC_ASSERT(kSmiTagSize == 1 && kSmiShiftSize == 0);
151 __ lea(esp, Operand(esp, unused_reg, times_half_pointer_size, 0)); 134 __ lea(esp, Operand(esp, unused_reg, times_half_pointer_size, 0));
152 135
153 // Get rid of the internal frame. 136 // Get rid of the internal frame.
154 } 137 }
155 138
156 // If this call did not replace a call but patched other code then there will 139 // This call did not replace a call , so there will be an unwanted
157 // be an unwanted return address left on the stack. Here we get rid of that. 140 // return address left on the stack. Here we get rid of that.
158 if (convert_call_to_jmp) { 141 __ add(esp, Immediate(kPointerSize));
159 __ add(esp, Immediate(kPointerSize));
160 }
161 142
162 // Now that the break point has been handled, resume normal execution by 143 // Now that the break point has been handled, resume normal execution by
163 // jumping to the target address intended by the caller and that was 144 // jumping to the target address intended by the caller and that was
164 // overwritten by the address of DebugBreakXXX. 145 // overwritten by the address of DebugBreakXXX.
165 ExternalReference after_break_target = 146 ExternalReference after_break_target =
166 ExternalReference::debug_after_break_target_address(masm->isolate()); 147 ExternalReference::debug_after_break_target_address(masm->isolate());
167 __ jmp(Operand::StaticVariable(after_break_target)); 148 __ jmp(Operand::StaticVariable(after_break_target));
168 } 149 }
169 150
170 151
171 void DebugCodegen::GenerateCallICStubDebugBreak(MacroAssembler* masm) {
172 // Register state for CallICStub
173 // ----------- S t a t e -------------
174 // -- edx : type feedback slot (smi)
175 // -- edi : function
176 // -----------------------------------
177 Generate_DebugBreakCallHelper(masm, edx.bit() | edi.bit(),
178 0, false);
179 }
180
181
182 void DebugCodegen::GenerateReturnDebugBreak(MacroAssembler* masm) { 152 void DebugCodegen::GenerateReturnDebugBreak(MacroAssembler* masm) {
183 // Register state just before return from JS function (from codegen-ia32.cc). 153 // Register state just before return from JS function (from codegen-ia32.cc).
184 // ----------- S t a t e ------------- 154 // ----------- S t a t e -------------
185 // -- eax: return value 155 // -- eax: return value
186 // ----------------------------------- 156 // -----------------------------------
187 Generate_DebugBreakCallHelper(masm, eax.bit(), 0, true); 157 Generate_DebugBreakCallHelper(masm, eax.bit());
188 } 158 }
189 159
190 160
191 void DebugCodegen::GenerateCallFunctionStubDebugBreak(MacroAssembler* masm) {
192 // Register state for CallFunctionStub (from code-stubs-ia32.cc).
193 // ----------- S t a t e -------------
194 // -- edi: function
195 // -----------------------------------
196 Generate_DebugBreakCallHelper(masm, edi.bit(), 0, false);
197 }
198
199
200 void DebugCodegen::GenerateCallConstructStubDebugBreak(MacroAssembler* masm) {
201 // Register state for CallConstructStub (from code-stubs-ia32.cc).
202 // eax is the actual number of arguments not encoded as a smi see comment
203 // above IC call.
204 // ----------- S t a t e -------------
205 // -- eax: number of arguments (not smi)
206 // -- edi: constructor function
207 // -----------------------------------
208 // The number of arguments in eax is not smi encoded.
209 Generate_DebugBreakCallHelper(masm, edi.bit(), eax.bit(), false);
210 }
211
212
213 void DebugCodegen::GenerateCallConstructStubRecordDebugBreak(
214 MacroAssembler* masm) {
215 // Register state for CallConstructStub (from code-stubs-ia32.cc).
216 // eax is the actual number of arguments not encoded as a smi see comment
217 // above IC call.
218 // ----------- S t a t e -------------
219 // -- eax: number of arguments (not smi)
220 // -- ebx: feedback array
221 // -- edx: feedback slot (smi)
222 // -- edi: constructor function
223 // -----------------------------------
224 // The number of arguments in eax is not smi encoded.
225 Generate_DebugBreakCallHelper(masm, ebx.bit() | edx.bit() | edi.bit(),
226 eax.bit(), false);
227 }
228
229
230 void DebugCodegen::GenerateSlot(MacroAssembler* masm) { 161 void DebugCodegen::GenerateSlot(MacroAssembler* masm) {
231 // Generate enough nop's to make space for a call instruction. 162 // Generate enough nop's to make space for a call instruction.
232 Label check_codesize; 163 Label check_codesize;
233 __ bind(&check_codesize); 164 __ bind(&check_codesize);
234 __ RecordDebugBreakSlot();
235 __ Nop(Assembler::kDebugBreakSlotLength); 165 __ Nop(Assembler::kDebugBreakSlotLength);
236 DCHECK_EQ(Assembler::kDebugBreakSlotLength, 166 DCHECK_EQ(Assembler::kDebugBreakSlotLength,
237 masm->SizeOfCodeGeneratedSince(&check_codesize)); 167 masm->SizeOfCodeGeneratedSince(&check_codesize));
238 } 168 }
239 169
240 170
241 void DebugCodegen::GenerateSlotDebugBreak(MacroAssembler* masm) { 171 void DebugCodegen::GenerateSlotDebugBreak(MacroAssembler* masm) {
242 Generate_DebugBreakCallHelper(masm, 0, 0, true); 172 Generate_DebugBreakCallHelper(masm, 0);
243 } 173 }
244 174
245 175
246 void DebugCodegen::GeneratePlainReturnLiveEdit(MacroAssembler* masm) { 176 void DebugCodegen::GeneratePlainReturnLiveEdit(MacroAssembler* masm) {
247 masm->ret(0); 177 masm->ret(0);
248 } 178 }
249 179
250 180
251 void DebugCodegen::GenerateFrameDropperLiveEdit(MacroAssembler* masm) { 181 void DebugCodegen::GenerateFrameDropperLiveEdit(MacroAssembler* masm) {
252 ExternalReference restarter_frame_function_slot = 182 ExternalReference restarter_frame_function_slot =
(...skipping 21 matching lines...) Expand all
274 204
275 205
276 const bool LiveEdit::kFrameDropperSupported = true; 206 const bool LiveEdit::kFrameDropperSupported = true;
277 207
278 #undef __ 208 #undef __
279 209
280 } // namespace internal 210 } // namespace internal
281 } // namespace v8 211 } // namespace v8
282 212
283 #endif // V8_TARGET_ARCH_IA32 213 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/ia32/assembler-ia32.h ('k') | src/ia32/full-codegen-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698