OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 #if V8_TARGET_ARCH_ARM64 | 5 #if V8_TARGET_ARCH_ARM64 |
6 | 6 |
7 #include "src/debug/debug.h" | 7 #include "src/debug/debug.h" |
8 | 8 |
9 #include "src/arm64/frames-arm64.h" | 9 #include "src/arm64/frames-arm64.h" |
10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
81 return !current_instr->IsNop(Assembler::DEBUG_BREAK_NOP); | 81 return !current_instr->IsNop(Assembler::DEBUG_BREAK_NOP); |
82 } | 82 } |
83 | 83 |
84 void DebugCodegen::GenerateDebugBreakStub(MacroAssembler* masm, | 84 void DebugCodegen::GenerateDebugBreakStub(MacroAssembler* masm, |
85 DebugBreakCallHelperMode mode) { | 85 DebugBreakCallHelperMode mode) { |
86 __ RecordComment("Debug break"); | 86 __ RecordComment("Debug break"); |
87 Register scratch = x10; | 87 Register scratch = x10; |
88 { | 88 { |
89 FrameScope scope(masm, StackFrame::INTERNAL); | 89 FrameScope scope(masm, StackFrame::INTERNAL); |
90 | 90 |
91 // Load padding words on stack. | |
92 __ Mov(scratch, Smi::FromInt(LiveEdit::kFramePaddingValue)); | |
93 __ PushMultipleTimes(scratch, LiveEdit::kFramePaddingInitialSize); | |
94 __ Mov(scratch, Smi::FromInt(LiveEdit::kFramePaddingInitialSize)); | |
95 __ Push(scratch); | |
96 | |
97 // Push arguments for DebugBreak call. | 91 // Push arguments for DebugBreak call. |
98 if (mode == SAVE_RESULT_REGISTER) { | 92 if (mode == SAVE_RESULT_REGISTER) { |
99 // Break on return. | 93 // Break on return. |
100 __ Push(x0); | 94 __ Push(x0); |
101 } else { | 95 } else { |
102 // Non-return breaks. | 96 // Non-return breaks. |
103 __ Push(masm->isolate()->factory()->the_hole_value()); | 97 __ Push(masm->isolate()->factory()->the_hole_value()); |
104 } | 98 } |
105 __ Mov(x0, 1); | 99 __ Mov(x0, 1); |
106 __ Mov(x1, ExternalReference(Runtime::FunctionForId(Runtime::kDebugBreak), | 100 __ Mov(x1, ExternalReference(Runtime::FunctionForId(Runtime::kDebugBreak), |
107 masm->isolate())); | 101 masm->isolate())); |
108 | 102 |
109 CEntryStub stub(masm->isolate(), 1); | 103 CEntryStub stub(masm->isolate(), 1); |
110 __ CallStub(&stub); | 104 __ CallStub(&stub); |
111 | 105 |
112 if (FLAG_debug_code) { | 106 if (FLAG_debug_code) { |
113 for (int i = 0; i < kNumJSCallerSaved; i++) { | 107 for (int i = 0; i < kNumJSCallerSaved; i++) { |
114 Register reg = Register::XRegFromCode(JSCallerSavedCode(i)); | 108 Register reg = Register::XRegFromCode(JSCallerSavedCode(i)); |
115 // Do not clobber x0 if mode is SAVE_RESULT_REGISTER. It will | 109 // Do not clobber x0 if mode is SAVE_RESULT_REGISTER. It will |
116 // contain return value of the function. | 110 // contain return value of the function. |
117 if (!(reg.is(x0) && (mode == SAVE_RESULT_REGISTER))) { | 111 if (!(reg.is(x0) && (mode == SAVE_RESULT_REGISTER))) { |
118 __ Mov(reg, Operand(kDebugZapValue)); | 112 __ Mov(reg, Operand(kDebugZapValue)); |
119 } | 113 } |
120 } | 114 } |
121 } | 115 } |
122 | |
123 // Don't bother removing padding bytes pushed on the stack | |
124 // as the frame is going to be restored right away. | |
125 | |
126 // Leave the internal frame. | 116 // Leave the internal frame. |
127 } | 117 } |
128 | 118 |
129 // Now that the break point has been handled, resume normal execution by | 119 __ MaybeDropFrames(); |
130 // jumping to the target address intended by the caller and that was | 120 |
131 // overwritten by the address of DebugBreakXXX. | 121 // Return to caller. |
132 ExternalReference after_break_target = | 122 __ Ret(); |
133 ExternalReference::debug_after_break_target_address(masm->isolate()); | 123 } |
134 __ Mov(scratch, after_break_target); | 124 |
135 __ Ldr(scratch, MemOperand(scratch)); | 125 void DebugCodegen::GenerateHandleDebuggerStatement(MacroAssembler* masm) { |
136 __ Br(scratch); | 126 { |
| 127 FrameScope scope(masm, StackFrame::INTERNAL); |
| 128 __ CallRuntime(Runtime::kHandleDebuggerStatement, 0); |
| 129 } |
| 130 __ MaybeDropFrames(); |
| 131 |
| 132 // Return to caller. |
| 133 __ Ret(); |
| 134 } |
| 135 |
| 136 void DebugCodegen::GenerateFrameDropperTrampoline(MacroAssembler* masm) { |
| 137 // Frame is being dropped: |
| 138 // - Drop to the target frame specified by x1. |
| 139 // - Look up current function on the frame. |
| 140 // - Leave the frame. |
| 141 // - Restart the frame by calling the function. |
| 142 __ Mov(fp, x1); |
| 143 __ AssertStackConsistency(); |
| 144 __ Ldr(x1, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
| 145 |
| 146 __ Mov(masm->StackPointer(), Operand(fp)); |
| 147 __ Pop(fp, lr); // Frame, Return address. |
| 148 |
| 149 __ Ldr(x0, FieldMemOperand(x1, JSFunction::kSharedFunctionInfoOffset)); |
| 150 __ Ldr(x0, |
| 151 FieldMemOperand(x0, SharedFunctionInfo::kFormalParameterCountOffset)); |
| 152 __ mov(x2, x0); |
| 153 |
| 154 ParameterCount dummy1(x2); |
| 155 ParameterCount dummy2(x0); |
| 156 __ InvokeFunction(x1, dummy1, dummy2, JUMP_FUNCTION, |
| 157 CheckDebugStepCallWrapper()); |
137 } | 158 } |
138 | 159 |
139 | 160 |
140 void DebugCodegen::GenerateFrameDropperLiveEdit(MacroAssembler* masm) { | |
141 // We do not know our frame height, but set sp based on fp. | |
142 __ Add(masm->StackPointer(), fp, FrameDropperFrameConstants::kFunctionOffset); | |
143 __ AssertStackConsistency(); | |
144 | |
145 __ Pop(x1); // Function | |
146 __ Mov(masm->StackPointer(), Operand(fp)); | |
147 __ Pop(fp, lr); // Frame, Return address. | |
148 | |
149 ParameterCount dummy(0); | |
150 __ CheckDebugHook(x1, no_reg, dummy, dummy); | |
151 | |
152 UseScratchRegisterScope temps(masm); | |
153 Register scratch = temps.AcquireX(); | |
154 | |
155 // Load context from the function. | |
156 __ Ldr(cp, FieldMemOperand(x1, JSFunction::kContextOffset)); | |
157 | |
158 // Clear new.target as a safety measure. | |
159 __ LoadRoot(x3, Heap::kUndefinedValueRootIndex); | |
160 | |
161 // Get function code. | |
162 __ Ldr(scratch, FieldMemOperand(x1, JSFunction::kSharedFunctionInfoOffset)); | |
163 __ Ldr(scratch, FieldMemOperand(scratch, SharedFunctionInfo::kCodeOffset)); | |
164 __ Add(scratch, scratch, Code::kHeaderSize - kHeapObjectTag); | |
165 | |
166 // Re-run JSFunction, x1 is function, cp is context. | |
167 __ Br(scratch); | |
168 } | |
169 | |
170 | |
171 const bool LiveEdit::kFrameDropperSupported = true; | 161 const bool LiveEdit::kFrameDropperSupported = true; |
172 | 162 |
173 } // namespace internal | 163 } // namespace internal |
174 } // namespace v8 | 164 } // namespace v8 |
175 | 165 |
176 #endif // V8_TARGET_ARCH_ARM64 | 166 #endif // V8_TARGET_ARCH_ARM64 |
OLD | NEW |