OLD | NEW |
---|---|
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 bool BreakLocationIterator::IsDebugBreakAtReturn() { | 15 bool BreakLocationIterator::IsDebugBreakAtReturn() { |
16 return Debug::IsDebugBreakAtReturn(rinfo()); | 16 return Debug::IsDebugBreakAtReturn(rinfo()); |
17 } | 17 } |
18 | 18 |
19 | 19 |
20 void BreakLocationIterator::SetDebugBreakAtReturn() { | 20 void BreakLocationIterator::SetDebugBreakAtReturn() { |
21 // Patch the code changing the return from JS function sequence from | 21 // Patch the code changing the return from JS function sequence from |
22 // mov sp, fp | 22 // mov sp, fp |
23 // ldmia sp!, {fp, lr} | 23 // ldmia sp!, {fp, lr} |
24 // add sp, sp, #4 | 24 // add sp, sp, #4 |
25 // bx lr | 25 // bx lr |
26 // to a call to the debug break return code. | 26 // to a call to the debug break return code. |
27 // ldr ip, [pc, #0] | 27 // ldr ip, [pc, #0] |
28 // blx ip | 28 // blx ip |
29 // <debug break return code entry point address> | 29 // <debug break return code entry point address> |
30 // bktp 0 | 30 // bkpt 0 |
31 CodePatcher patcher(rinfo()->pc(), Assembler::kJSReturnSequenceInstructions); | 31 CodePatcher patcher(rinfo()->pc(), Assembler::kJSReturnSequenceInstructions); |
32 patcher.masm()->ldr(v8::internal::ip, MemOperand(v8::internal::pc, 0)); | 32 patcher.masm()->ldr(v8::internal::ip, MemOperand(v8::internal::pc, 0)); |
33 patcher.masm()->blx(v8::internal::ip); | 33 patcher.masm()->blx(v8::internal::ip); |
34 patcher.Emit( | 34 patcher.Emit( |
35 debug_info_->GetIsolate()->builtins()->Return_DebugBreak()->entry()); | 35 debug_info_->GetIsolate()->builtins()->Return_DebugBreak()->entry()); |
36 patcher.masm()->bkpt(0); | 36 patcher.masm()->bkpt(0); |
37 } | 37 } |
38 | 38 |
39 | 39 |
40 // Restore the JS frame exit code. | 40 // Restore the JS frame exit code. |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
86 | 86 |
87 #define __ ACCESS_MASM(masm) | 87 #define __ ACCESS_MASM(masm) |
88 | 88 |
89 | 89 |
90 static void Generate_DebugBreakCallHelper(MacroAssembler* masm, | 90 static void Generate_DebugBreakCallHelper(MacroAssembler* masm, |
91 RegList object_regs, | 91 RegList object_regs, |
92 RegList non_object_regs) { | 92 RegList non_object_regs) { |
93 { | 93 { |
94 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); | 94 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); |
95 | 95 |
96 // Load padding words on stack. | |
97 __ mov(ip, Operand(Smi::FromInt(LiveEdit::kFramePaddingValue))); | |
98 for (int i = 0; i < LiveEdit::kFramePaddingInitialSize; i++) { | |
99 __ push(ip); | |
100 } | |
101 __ mov(ip, Operand(Smi::FromInt(LiveEdit::kFramePaddingInitialSize))); | |
102 __ push(ip); | |
103 | |
96 // Store the registers containing live values on the expression stack to | 104 // Store the registers containing live values on the expression stack to |
97 // make sure that these are correctly updated during GC. Non object values | 105 // make sure that these are correctly updated during GC. Non object values |
98 // are stored as a smi causing it to be untouched by GC. | 106 // are stored as a smi causing it to be untouched by GC. |
99 ASSERT((object_regs & ~kJSCallerSaved) == 0); | 107 ASSERT((object_regs & ~kJSCallerSaved) == 0); |
100 ASSERT((non_object_regs & ~kJSCallerSaved) == 0); | 108 ASSERT((non_object_regs & ~kJSCallerSaved) == 0); |
101 ASSERT((object_regs & non_object_regs) == 0); | 109 ASSERT((object_regs & non_object_regs) == 0); |
102 if ((object_regs | non_object_regs) != 0) { | 110 if ((object_regs | non_object_regs) != 0) { |
103 for (int i = 0; i < kNumJSCallerSaved; i++) { | 111 for (int i = 0; i < kNumJSCallerSaved; i++) { |
104 int r = JSCallerSavedCode(i); | 112 int r = JSCallerSavedCode(i); |
105 Register reg = { r }; | 113 Register reg = { r }; |
(...skipping 26 matching lines...) Expand all Loading... | |
132 if ((non_object_regs & (1 << r)) != 0) { | 140 if ((non_object_regs & (1 << r)) != 0) { |
133 __ SmiUntag(reg); | 141 __ SmiUntag(reg); |
134 } | 142 } |
135 if (FLAG_debug_code && | 143 if (FLAG_debug_code && |
136 (((object_regs |non_object_regs) & (1 << r)) == 0)) { | 144 (((object_regs |non_object_regs) & (1 << r)) == 0)) { |
137 __ mov(reg, Operand(kDebugZapValue)); | 145 __ mov(reg, Operand(kDebugZapValue)); |
138 } | 146 } |
139 } | 147 } |
140 } | 148 } |
141 | 149 |
150 // Don't bother removing padding bytes pushed on the stack | |
151 // as the frame is going to be restored right away. | |
152 | |
Yang
2014/06/18 15:03:55
Are you sure this is correct? A brief comparison t
alph
2014/06/18 16:29:21
FrameAndConstantPoolScope destructor is called her
| |
142 // Leave the internal frame. | 153 // Leave the internal frame. |
143 } | 154 } |
144 | 155 |
145 // Now that the break point has been handled, resume normal execution by | 156 // Now that the break point has been handled, resume normal execution by |
146 // jumping to the target address intended by the caller and that was | 157 // jumping to the target address intended by the caller and that was |
147 // overwritten by the address of DebugBreakXXX. | 158 // overwritten by the address of DebugBreakXXX. |
148 ExternalReference after_break_target = | 159 ExternalReference after_break_target = |
149 ExternalReference::debug_after_break_target_address(masm->isolate()); | 160 ExternalReference::debug_after_break_target_address(masm->isolate()); |
150 __ mov(ip, Operand(after_break_target)); | 161 __ mov(ip, Operand(after_break_target)); |
151 __ ldr(ip, MemOperand(ip)); | 162 __ ldr(ip, MemOperand(ip)); |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
275 | 286 |
276 | 287 |
277 void DebugCodegen::GenerateSlotDebugBreak(MacroAssembler* masm) { | 288 void DebugCodegen::GenerateSlotDebugBreak(MacroAssembler* masm) { |
278 // In the places where a debug break slot is inserted no registers can contain | 289 // In the places where a debug break slot is inserted no registers can contain |
279 // object pointers. | 290 // object pointers. |
280 Generate_DebugBreakCallHelper(masm, 0, 0); | 291 Generate_DebugBreakCallHelper(masm, 0, 0); |
281 } | 292 } |
282 | 293 |
283 | 294 |
284 void DebugCodegen::GeneratePlainReturnLiveEdit(MacroAssembler* masm) { | 295 void DebugCodegen::GeneratePlainReturnLiveEdit(MacroAssembler* masm) { |
285 masm->Abort(kLiveEditFrameDroppingIsNotSupportedOnArm); | 296 __ Ret(); |
286 } | 297 } |
287 | 298 |
288 | 299 |
289 void DebugCodegen::GenerateFrameDropperLiveEdit(MacroAssembler* masm) { | 300 void DebugCodegen::GenerateFrameDropperLiveEdit(MacroAssembler* masm) { |
290 masm->Abort(kLiveEditFrameDroppingIsNotSupportedOnArm); | 301 ExternalReference restarter_frame_function_slot = |
302 ExternalReference::debug_restarter_frame_function_pointer_address( | |
303 masm->isolate()); | |
304 __ mov(ip, Operand(restarter_frame_function_slot)); | |
305 __ mov(r1, Operand::Zero()); | |
306 __ str(r1, MemOperand(ip, 0)); | |
307 | |
308 // We do not know our frame height, but set sp based on fp. | |
309 __ sub(sp, fp, Operand(kPointerSize)); | |
310 | |
311 __ Pop(lr, fp, r1); // Return address, Frame, Function. | |
312 | |
313 // Load context from the function. | |
314 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); | |
315 | |
316 // Get function code. | |
317 __ ldr(ip, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); | |
318 __ ldr(ip, FieldMemOperand(ip, SharedFunctionInfo::kCodeOffset)); | |
319 __ add(ip, ip, Operand(Code::kHeaderSize - kHeapObjectTag)); | |
320 | |
321 // Re-run JSFunction, r1 is function, cp is context. | |
322 __ Jump(ip); | |
291 } | 323 } |
292 | 324 |
293 | 325 |
294 const bool LiveEdit::kFrameDropperSupported = false; | 326 const bool LiveEdit::kFrameDropperSupported = true; |
295 | 327 |
296 #undef __ | 328 #undef __ |
297 | 329 |
298 } } // namespace v8::internal | 330 } } // namespace v8::internal |
299 | 331 |
300 #endif // V8_TARGET_ARCH_ARM | 332 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |