OLD | NEW |
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
123 ASSERT(IsDebugBreakSlot()); | 123 ASSERT(IsDebugBreakSlot()); |
124 rinfo()->PatchCode(original_rinfo()->pc(), | 124 rinfo()->PatchCode(original_rinfo()->pc(), |
125 Assembler::kDebugBreakSlotInstructions); | 125 Assembler::kDebugBreakSlotInstructions); |
126 } | 126 } |
127 | 127 |
128 | 128 |
129 #define __ ACCESS_MASM(masm) | 129 #define __ ACCESS_MASM(masm) |
130 | 130 |
131 | 131 |
132 static void Generate_DebugBreakCallHelper(MacroAssembler* masm, | 132 static void Generate_DebugBreakCallHelper(MacroAssembler* masm, |
133 RegList pointer_regs) { | 133 RegList object_regs, |
134 // Save the content of all general purpose registers in memory. This copy in | 134 RegList non_object_regs) { |
135 // memory is later pushed onto the JS expression stack for the fake JS frame | |
136 // generated and also to the C frame generated on top of that. In the JS | |
137 // frame ONLY the registers containing pointers will be pushed on the | |
138 // expression stack. This causes the GC to update these pointers so that | |
139 // they will have the correct value when returning from the debugger. | |
140 __ SaveRegistersToMemory(kJSCallerSaved); | |
141 | |
142 __ EnterInternalFrame(); | 135 __ EnterInternalFrame(); |
143 | 136 |
144 // Store the registers containing object pointers on the expression stack to | 137 // Store the registers containing live values on the expression stack to |
145 // make sure that these are correctly updated during GC. | 138 // make sure that these are correctly updated during GC. Non object values |
146 // Use sp as base to push. | 139 // are stored as a smi causing it to be untouched by GC. |
147 __ CopyRegistersFromMemoryToStack(sp, pointer_regs); | 140 ASSERT((object_regs & ~kJSCallerSaved) == 0); |
| 141 ASSERT((non_object_regs & ~kJSCallerSaved) == 0); |
| 142 ASSERT((object_regs & non_object_regs) == 0); |
| 143 if ((object_regs | non_object_regs) != 0) { |
| 144 for (int i = 0; i < kNumJSCallerSaved; i++) { |
| 145 int r = JSCallerSavedCode(i); |
| 146 Register reg = { r }; |
| 147 if ((non_object_regs & (1 << r)) != 0) { |
| 148 if (FLAG_debug_code) { |
| 149 __ tst(reg, Operand(0xc0000000)); |
| 150 __ Assert(eq, "Unable to encode value as smi"); |
| 151 } |
| 152 __ mov(reg, Operand(reg, LSL, kSmiTagSize)); |
| 153 } |
| 154 } |
| 155 __ stm(db_w, sp, object_regs | non_object_regs); |
| 156 } |
148 | 157 |
149 #ifdef DEBUG | 158 #ifdef DEBUG |
150 __ RecordComment("// Calling from debug break to runtime - come in - over"); | 159 __ RecordComment("// Calling from debug break to runtime - come in - over"); |
151 #endif | 160 #endif |
152 __ mov(r0, Operand(0)); // no arguments | 161 __ mov(r0, Operand(0)); // no arguments |
153 __ mov(r1, Operand(ExternalReference::debug_break())); | 162 __ mov(r1, Operand(ExternalReference::debug_break())); |
154 | 163 |
155 CEntryStub ceb(1, ExitFrame::MODE_DEBUG); | 164 CEntryStub ceb(1); |
156 __ CallStub(&ceb); | 165 __ CallStub(&ceb); |
157 | 166 |
158 // Restore the register values containing object pointers from the expression | 167 // Restore the register values from the expression stack. |
159 // stack in the reverse order as they where pushed. | 168 if ((object_regs | non_object_regs) != 0) { |
160 // Use sp as base to pop. | 169 __ ldm(ia_w, sp, object_regs | non_object_regs); |
161 __ CopyRegistersFromStackToMemory(sp, r3, pointer_regs); | 170 for (int i = 0; i < kNumJSCallerSaved; i++) { |
| 171 int r = JSCallerSavedCode(i); |
| 172 Register reg = { r }; |
| 173 if ((non_object_regs & (1 << r)) != 0) { |
| 174 __ mov(reg, Operand(reg, LSR, kSmiTagSize)); |
| 175 } |
| 176 if (FLAG_debug_code && |
| 177 (((object_regs |non_object_regs) & (1 << r)) == 0)) { |
| 178 __ mov(reg, Operand(kDebugZapValue)); |
| 179 } |
| 180 } |
| 181 } |
162 | 182 |
163 __ LeaveInternalFrame(); | 183 __ LeaveInternalFrame(); |
164 | 184 |
165 // Finally restore all registers. | |
166 __ RestoreRegistersFromMemory(kJSCallerSaved); | |
167 | |
168 // Now that the break point has been handled, resume normal execution by | 185 // Now that the break point has been handled, resume normal execution by |
169 // jumping to the target address intended by the caller and that was | 186 // jumping to the target address intended by the caller and that was |
170 // overwritten by the address of DebugBreakXXX. | 187 // overwritten by the address of DebugBreakXXX. |
171 __ mov(ip, Operand(ExternalReference(Debug_Address::AfterBreakTarget()))); | 188 __ mov(ip, Operand(ExternalReference(Debug_Address::AfterBreakTarget()))); |
172 __ ldr(ip, MemOperand(ip)); | 189 __ ldr(ip, MemOperand(ip)); |
173 __ Jump(ip); | 190 __ Jump(ip); |
174 } | 191 } |
175 | 192 |
176 | 193 |
177 void Debug::GenerateLoadICDebugBreak(MacroAssembler* masm) { | 194 void Debug::GenerateLoadICDebugBreak(MacroAssembler* masm) { |
178 // Calling convention for IC load (from ic-arm.cc). | 195 // Calling convention for IC load (from ic-arm.cc). |
179 // ----------- S t a t e ------------- | 196 // ----------- S t a t e ------------- |
180 // -- r2 : name | 197 // -- r2 : name |
181 // -- lr : return address | 198 // -- lr : return address |
182 // -- r0 : receiver | 199 // -- r0 : receiver |
183 // -- [sp] : receiver | 200 // -- [sp] : receiver |
184 // ----------------------------------- | 201 // ----------------------------------- |
185 // Registers r0 and r2 contain objects that need to be pushed on the | 202 // Registers r0 and r2 contain objects that need to be pushed on the |
186 // expression stack of the fake JS frame. | 203 // expression stack of the fake JS frame. |
187 Generate_DebugBreakCallHelper(masm, r0.bit() | r2.bit()); | 204 Generate_DebugBreakCallHelper(masm, r0.bit() | r2.bit(), 0); |
188 } | 205 } |
189 | 206 |
190 | 207 |
191 void Debug::GenerateStoreICDebugBreak(MacroAssembler* masm) { | 208 void Debug::GenerateStoreICDebugBreak(MacroAssembler* masm) { |
192 // Calling convention for IC store (from ic-arm.cc). | 209 // Calling convention for IC store (from ic-arm.cc). |
193 // ----------- S t a t e ------------- | 210 // ----------- S t a t e ------------- |
194 // -- r0 : value | 211 // -- r0 : value |
195 // -- r1 : receiver | 212 // -- r1 : receiver |
196 // -- r2 : name | 213 // -- r2 : name |
197 // -- lr : return address | 214 // -- lr : return address |
198 // ----------------------------------- | 215 // ----------------------------------- |
199 // Registers r0, r1, and r2 contain objects that need to be pushed on the | 216 // Registers r0, r1, and r2 contain objects that need to be pushed on the |
200 // expression stack of the fake JS frame. | 217 // expression stack of the fake JS frame. |
201 Generate_DebugBreakCallHelper(masm, r0.bit() | r1.bit() | r2.bit()); | 218 Generate_DebugBreakCallHelper(masm, r0.bit() | r1.bit() | r2.bit(), 0); |
202 } | 219 } |
203 | 220 |
204 | 221 |
205 void Debug::GenerateKeyedLoadICDebugBreak(MacroAssembler* masm) { | 222 void Debug::GenerateKeyedLoadICDebugBreak(MacroAssembler* masm) { |
206 // ---------- S t a t e -------------- | 223 // ---------- S t a t e -------------- |
207 // -- lr : return address | 224 // -- lr : return address |
208 // -- r0 : key | 225 // -- r0 : key |
209 // -- sp[0] : key | 226 // -- r1 : receiver |
210 // -- sp[4] : receiver | 227 Generate_DebugBreakCallHelper(masm, r0.bit() | r1.bit(), 0); |
211 Generate_DebugBreakCallHelper(masm, r0.bit()); | |
212 } | 228 } |
213 | 229 |
214 | 230 |
215 void Debug::GenerateKeyedStoreICDebugBreak(MacroAssembler* masm) { | 231 void Debug::GenerateKeyedStoreICDebugBreak(MacroAssembler* masm) { |
216 // ---------- S t a t e -------------- | 232 // ---------- S t a t e -------------- |
217 // -- r0 : value | 233 // -- r0 : value |
218 // -- r1 : key | 234 // -- r1 : key |
219 // -- r2 : receiver | 235 // -- r2 : receiver |
220 // -- lr : return address | 236 // -- lr : return address |
221 Generate_DebugBreakCallHelper(masm, r0.bit() | r1.bit() | r2.bit()); | 237 Generate_DebugBreakCallHelper(masm, r0.bit() | r1.bit() | r2.bit(), 0); |
222 } | 238 } |
223 | 239 |
224 | 240 |
225 void Debug::GenerateCallICDebugBreak(MacroAssembler* masm) { | 241 void Debug::GenerateCallICDebugBreak(MacroAssembler* masm) { |
226 // Calling convention for IC call (from ic-arm.cc) | 242 // Calling convention for IC call (from ic-arm.cc) |
227 // ----------- S t a t e ------------- | 243 // ----------- S t a t e ------------- |
228 // -- r2: name | 244 // -- r2 : name |
229 // ----------------------------------- | 245 // ----------------------------------- |
230 Generate_DebugBreakCallHelper(masm, r2.bit()); | 246 Generate_DebugBreakCallHelper(masm, r2.bit(), 0); |
231 } | 247 } |
232 | 248 |
233 | 249 |
234 void Debug::GenerateConstructCallDebugBreak(MacroAssembler* masm) { | 250 void Debug::GenerateConstructCallDebugBreak(MacroAssembler* masm) { |
235 // In places other than IC call sites it is expected that r0 is TOS which | 251 // Calling convention for construct call (from builtins-arm.cc) |
236 // is an object - this is not generally the case so this should be used with | 252 // -- r0 : number of arguments (not smi) |
237 // care. | 253 // -- r1 : constructor function |
238 Generate_DebugBreakCallHelper(masm, r0.bit()); | 254 Generate_DebugBreakCallHelper(masm, r1.bit(), r0.bit()); |
239 } | 255 } |
240 | 256 |
241 | 257 |
242 void Debug::GenerateReturnDebugBreak(MacroAssembler* masm) { | 258 void Debug::GenerateReturnDebugBreak(MacroAssembler* masm) { |
243 // In places other than IC call sites it is expected that r0 is TOS which | 259 // In places other than IC call sites it is expected that r0 is TOS which |
244 // is an object - this is not generally the case so this should be used with | 260 // is an object - this is not generally the case so this should be used with |
245 // care. | 261 // care. |
246 Generate_DebugBreakCallHelper(masm, r0.bit()); | 262 Generate_DebugBreakCallHelper(masm, r0.bit(), 0); |
247 } | 263 } |
248 | 264 |
249 | 265 |
250 void Debug::GenerateStubNoRegistersDebugBreak(MacroAssembler* masm) { | 266 void Debug::GenerateStubNoRegistersDebugBreak(MacroAssembler* masm) { |
251 // ----------- S t a t e ------------- | 267 // ----------- S t a t e ------------- |
252 // No registers used on entry. | 268 // No registers used on entry. |
253 // ----------------------------------- | 269 // ----------------------------------- |
254 Generate_DebugBreakCallHelper(masm, 0); | 270 Generate_DebugBreakCallHelper(masm, 0, 0); |
255 } | 271 } |
256 | 272 |
257 | 273 |
258 void Debug::GenerateSlot(MacroAssembler* masm) { | 274 void Debug::GenerateSlot(MacroAssembler* masm) { |
259 // Generate enough nop's to make space for a call instruction. Avoid emitting | 275 // Generate enough nop's to make space for a call instruction. Avoid emitting |
260 // the constant pool in the debug break slot code. | 276 // the constant pool in the debug break slot code. |
261 Assembler::BlockConstPoolScope block_const_pool(masm); | 277 Assembler::BlockConstPoolScope block_const_pool(masm); |
262 Label check_codesize; | 278 Label check_codesize; |
263 __ bind(&check_codesize); | 279 __ bind(&check_codesize); |
264 __ RecordDebugBreakSlot(); | 280 __ RecordDebugBreakSlot(); |
265 for (int i = 0; i < Assembler::kDebugBreakSlotInstructions; i++) { | 281 for (int i = 0; i < Assembler::kDebugBreakSlotInstructions; i++) { |
266 __ nop(2); | 282 __ nop(2); |
267 } | 283 } |
268 ASSERT_EQ(Assembler::kDebugBreakSlotInstructions, | 284 ASSERT_EQ(Assembler::kDebugBreakSlotInstructions, |
269 masm->InstructionsGeneratedSince(&check_codesize)); | 285 masm->InstructionsGeneratedSince(&check_codesize)); |
270 } | 286 } |
271 | 287 |
272 | 288 |
273 void Debug::GenerateSlotDebugBreak(MacroAssembler* masm) { | 289 void Debug::GenerateSlotDebugBreak(MacroAssembler* masm) { |
274 // In the places where a debug break slot is inserted no registers can contain | 290 // In the places where a debug break slot is inserted no registers can contain |
275 // object pointers. | 291 // object pointers. |
276 Generate_DebugBreakCallHelper(masm, 0); | 292 Generate_DebugBreakCallHelper(masm, 0, 0); |
277 } | 293 } |
278 | 294 |
279 | 295 |
280 void Debug::GeneratePlainReturnLiveEdit(MacroAssembler* masm) { | 296 void Debug::GeneratePlainReturnLiveEdit(MacroAssembler* masm) { |
281 masm->Abort("LiveEdit frame dropping is not supported on arm"); | 297 masm->Abort("LiveEdit frame dropping is not supported on arm"); |
282 } | 298 } |
283 | 299 |
284 | 300 |
285 void Debug::GenerateFrameDropperLiveEdit(MacroAssembler* masm) { | 301 void Debug::GenerateFrameDropperLiveEdit(MacroAssembler* masm) { |
286 masm->Abort("LiveEdit frame dropping is not supported on arm"); | 302 masm->Abort("LiveEdit frame dropping is not supported on arm"); |
287 } | 303 } |
288 | 304 |
289 const bool Debug::kFrameDropperSupported = false; | 305 const bool Debug::kFrameDropperSupported = false; |
290 | 306 |
291 #undef __ | 307 #undef __ |
292 | 308 |
293 | 309 |
294 | 310 |
295 #endif // ENABLE_DEBUGGER_SUPPORT | 311 #endif // ENABLE_DEBUGGER_SUPPORT |
296 | 312 |
297 } } // namespace v8::internal | 313 } } // namespace v8::internal |
298 | 314 |
299 #endif // V8_TARGET_ARCH_ARM | 315 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |