| 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 |