OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // |
| 3 // Copyright IBM Corp. 2012, 2013. All rights reserved. |
| 4 // |
2 // Use of this source code is governed by a BSD-style license that can be | 5 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 6 // found in the LICENSE file. |
4 | 7 |
5 #include "src/v8.h" | 8 #include "src/v8.h" |
6 | 9 |
7 #if V8_TARGET_ARCH_ARM | 10 #if V8_TARGET_ARCH_PPC |
8 | 11 |
9 #include "src/codegen.h" | 12 #include "src/codegen.h" |
10 #include "src/debug.h" | 13 #include "src/debug.h" |
11 | 14 |
12 namespace v8 { | 15 namespace v8 { |
13 namespace internal { | 16 namespace internal { |
14 | 17 |
15 bool BreakLocationIterator::IsDebugBreakAtReturn() { | 18 bool BreakLocationIterator::IsDebugBreakAtReturn() { |
16 return Debug::IsDebugBreakAtReturn(rinfo()); | 19 return Debug::IsDebugBreakAtReturn(rinfo()); |
17 } | 20 } |
18 | 21 |
19 | 22 |
20 void BreakLocationIterator::SetDebugBreakAtReturn() { | 23 void BreakLocationIterator::SetDebugBreakAtReturn() { |
21 // Patch the code changing the return from JS function sequence from | 24 // Patch the code changing the return from JS function sequence from |
22 // mov sp, fp | 25 // |
23 // ldmia sp!, {fp, lr} | 26 // LeaveFrame |
24 // add sp, sp, #4 | 27 // addi sp, sp, <delta> |
25 // bx lr | 28 // blr |
| 29 // |
26 // to a call to the debug break return code. | 30 // to a call to the debug break return code. |
27 // ldr ip, [pc, #0] | 31 // this uses a FIXED_SEQUENCE to load an address constant |
28 // blx ip | 32 // |
29 // <debug break return code entry point address> | 33 // mov r0, <address> |
30 // bkpt 0 | 34 // mtlr r0 |
| 35 // blrl |
| 36 // bkpt |
| 37 // |
31 CodePatcher patcher(rinfo()->pc(), Assembler::kJSReturnSequenceInstructions); | 38 CodePatcher patcher(rinfo()->pc(), Assembler::kJSReturnSequenceInstructions); |
32 patcher.masm()->ldr(v8::internal::ip, MemOperand(v8::internal::pc, 0)); | 39 Assembler::BlockTrampolinePoolScope block_trampoline_pool(patcher.masm()); |
33 patcher.masm()->blx(v8::internal::ip); | 40 patcher.masm()->mov(v8::internal::r0, Operand(reinterpret_cast<intptr_t>( |
34 patcher.Emit( | 41 debug_info_->GetIsolate()->builtins()->Return_DebugBreak()->entry()))); |
35 debug_info_->GetIsolate()->builtins()->Return_DebugBreak()->entry()); | 42 patcher.masm()->mtlr(v8::internal::r0); |
| 43 patcher.masm()->bclr(BA, SetLK); |
36 patcher.masm()->bkpt(0); | 44 patcher.masm()->bkpt(0); |
37 } | 45 } |
38 | 46 |
39 | 47 |
40 // Restore the JS frame exit code. | 48 // Restore the JS frame exit code. |
41 void BreakLocationIterator::ClearDebugBreakAtReturn() { | 49 void BreakLocationIterator::ClearDebugBreakAtReturn() { |
42 rinfo()->PatchCode(original_rinfo()->pc(), | 50 rinfo()->PatchCode(original_rinfo()->pc(), |
43 Assembler::kJSReturnSequenceInstructions); | 51 Assembler::kJSReturnSequenceInstructions); |
44 } | 52 } |
45 | 53 |
46 | 54 |
47 // A debug break in the frame exit code is identified by the JS frame exit code | 55 // A debug break in the frame exit code is identified by the JS frame exit code |
48 // having been patched with a call instruction. | 56 // having been patched with a call instruction. |
49 bool Debug::IsDebugBreakAtReturn(RelocInfo* rinfo) { | 57 bool Debug::IsDebugBreakAtReturn(RelocInfo* rinfo) { |
50 ASSERT(RelocInfo::IsJSReturn(rinfo->rmode())); | 58 ASSERT(RelocInfo::IsJSReturn(rinfo->rmode())); |
51 return rinfo->IsPatchedReturnSequence(); | 59 return rinfo->IsPatchedReturnSequence(); |
52 } | 60 } |
53 | 61 |
54 | 62 |
55 bool BreakLocationIterator::IsDebugBreakAtSlot() { | 63 bool BreakLocationIterator::IsDebugBreakAtSlot() { |
56 ASSERT(IsDebugBreakSlot()); | 64 ASSERT(IsDebugBreakSlot()); |
57 // Check whether the debug break slot instructions have been patched. | 65 // Check whether the debug break slot instructions have been patched. |
58 return rinfo()->IsPatchedDebugBreakSlotSequence(); | 66 return rinfo()->IsPatchedDebugBreakSlotSequence(); |
59 } | 67 } |
60 | 68 |
61 | 69 |
62 void BreakLocationIterator::SetDebugBreakAtSlot() { | 70 void BreakLocationIterator::SetDebugBreakAtSlot() { |
63 ASSERT(IsDebugBreakSlot()); | 71 ASSERT(IsDebugBreakSlot()); |
64 // Patch the code changing the debug break slot code from | 72 // Patch the code changing the debug break slot code from |
65 // mov r2, r2 | 73 // |
66 // mov r2, r2 | 74 // ori r3, r3, 0 |
67 // mov r2, r2 | 75 // ori r3, r3, 0 |
68 // to a call to the debug break slot code. | 76 // ori r3, r3, 0 |
69 // ldr ip, [pc, #0] | 77 // ori r3, r3, 0 |
70 // blx ip | 78 // ori r3, r3, 0 |
71 // <debug break slot code entry point address> | 79 // |
| 80 // to a call to the debug break code, using a FIXED_SEQUENCE. |
| 81 // |
| 82 // mov r0, <address> |
| 83 // mtlr r0 |
| 84 // blrl |
| 85 // |
72 CodePatcher patcher(rinfo()->pc(), Assembler::kDebugBreakSlotInstructions); | 86 CodePatcher patcher(rinfo()->pc(), Assembler::kDebugBreakSlotInstructions); |
73 patcher.masm()->ldr(v8::internal::ip, MemOperand(v8::internal::pc, 0)); | 87 Assembler::BlockTrampolinePoolScope block_trampoline_pool(patcher.masm()); |
74 patcher.masm()->blx(v8::internal::ip); | 88 patcher.masm()->mov(v8::internal::r0, Operand(reinterpret_cast<intptr_t>( |
75 patcher.Emit( | 89 debug_info_->GetIsolate()->builtins()->Slot_DebugBreak()->entry()))); |
76 debug_info_->GetIsolate()->builtins()->Slot_DebugBreak()->entry()); | 90 patcher.masm()->mtlr(v8::internal::r0); |
| 91 patcher.masm()->bclr(BA, SetLK); |
77 } | 92 } |
78 | 93 |
79 | 94 |
80 void BreakLocationIterator::ClearDebugBreakAtSlot() { | 95 void BreakLocationIterator::ClearDebugBreakAtSlot() { |
81 ASSERT(IsDebugBreakSlot()); | 96 ASSERT(IsDebugBreakSlot()); |
82 rinfo()->PatchCode(original_rinfo()->pc(), | 97 rinfo()->PatchCode(original_rinfo()->pc(), |
83 Assembler::kDebugBreakSlotInstructions); | 98 Assembler::kDebugBreakSlotInstructions); |
84 } | 99 } |
85 | 100 |
86 | 101 |
87 #define __ ACCESS_MASM(masm) | 102 #define __ ACCESS_MASM(masm) |
88 | 103 |
89 | 104 |
90 static void Generate_DebugBreakCallHelper(MacroAssembler* masm, | 105 static void Generate_DebugBreakCallHelper(MacroAssembler* masm, |
91 RegList object_regs, | 106 RegList object_regs, |
92 RegList non_object_regs) { | 107 RegList non_object_regs) { |
93 { | 108 { |
94 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); | 109 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); |
95 | 110 |
96 // Load padding words on stack. | 111 // Load padding words on stack. |
97 __ mov(ip, Operand(Smi::FromInt(LiveEdit::kFramePaddingValue))); | 112 __ LoadSmiLiteral(ip, Smi::FromInt(LiveEdit::kFramePaddingValue)); |
98 for (int i = 0; i < LiveEdit::kFramePaddingInitialSize; i++) { | 113 for (int i = 0; i < LiveEdit::kFramePaddingInitialSize; i++) { |
99 __ push(ip); | 114 __ push(ip); |
100 } | 115 } |
101 __ mov(ip, Operand(Smi::FromInt(LiveEdit::kFramePaddingInitialSize))); | 116 __ LoadSmiLiteral(ip, Smi::FromInt(LiveEdit::kFramePaddingInitialSize)); |
102 __ push(ip); | 117 __ push(ip); |
103 | 118 |
104 // Store the registers containing live values on the expression stack to | 119 // Store the registers containing live values on the expression stack to |
105 // make sure that these are correctly updated during GC. Non object values | 120 // make sure that these are correctly updated during GC. Non object values |
106 // are stored as a smi causing it to be untouched by GC. | 121 // are stored as a smi causing it to be untouched by GC. |
107 ASSERT((object_regs & ~kJSCallerSaved) == 0); | 122 ASSERT((object_regs & ~kJSCallerSaved) == 0); |
108 ASSERT((non_object_regs & ~kJSCallerSaved) == 0); | 123 ASSERT((non_object_regs & ~kJSCallerSaved) == 0); |
109 ASSERT((object_regs & non_object_regs) == 0); | 124 ASSERT((object_regs & non_object_regs) == 0); |
110 if ((object_regs | non_object_regs) != 0) { | 125 if ((object_regs | non_object_regs) != 0) { |
111 for (int i = 0; i < kNumJSCallerSaved; i++) { | 126 for (int i = 0; i < kNumJSCallerSaved; i++) { |
112 int r = JSCallerSavedCode(i); | 127 int r = JSCallerSavedCode(i); |
113 Register reg = { r }; | 128 Register reg = { r }; |
114 if ((non_object_regs & (1 << r)) != 0) { | 129 if ((non_object_regs & (1 << r)) != 0) { |
115 if (FLAG_debug_code) { | 130 if (FLAG_debug_code) { |
116 __ tst(reg, Operand(0xc0000000)); | 131 __ TestUnsignedSmiCandidate(reg, r0); |
117 __ Assert(eq, kUnableToEncodeValueAsSmi); | 132 __ Assert(eq, kUnableToEncodeValueAsSmi, cr0); |
118 } | 133 } |
119 __ SmiTag(reg); | 134 __ SmiTag(reg); |
120 } | 135 } |
121 } | 136 } |
122 __ stm(db_w, sp, object_regs | non_object_regs); | 137 __ MultiPush(object_regs | non_object_regs); |
123 } | 138 } |
124 | 139 |
125 #ifdef DEBUG | 140 #ifdef DEBUG |
126 __ RecordComment("// Calling from debug break to runtime - come in - over"); | 141 __ RecordComment("// Calling from debug break to runtime - come in - over"); |
127 #endif | 142 #endif |
128 __ mov(r0, Operand::Zero()); // no arguments | 143 __ mov(r3, Operand::Zero()); // no arguments |
129 __ mov(r1, Operand(ExternalReference::debug_break(masm->isolate()))); | 144 __ mov(r4, Operand(ExternalReference::debug_break(masm->isolate()))); |
130 | 145 |
131 CEntryStub ceb(masm->isolate(), 1); | 146 CEntryStub ceb(masm->isolate(), 1); |
132 __ CallStub(&ceb); | 147 __ CallStub(&ceb); |
133 | 148 |
134 // Restore the register values from the expression stack. | 149 // Restore the register values from the expression stack. |
135 if ((object_regs | non_object_regs) != 0) { | 150 if ((object_regs | non_object_regs) != 0) { |
136 __ ldm(ia_w, sp, object_regs | non_object_regs); | 151 __ MultiPop(object_regs | non_object_regs); |
137 for (int i = 0; i < kNumJSCallerSaved; i++) { | 152 for (int i = 0; i < kNumJSCallerSaved; i++) { |
138 int r = JSCallerSavedCode(i); | 153 int r = JSCallerSavedCode(i); |
139 Register reg = { r }; | 154 Register reg = { r }; |
140 if ((non_object_regs & (1 << r)) != 0) { | 155 if ((non_object_regs & (1 << r)) != 0) { |
141 __ SmiUntag(reg); | 156 __ SmiUntag(reg); |
142 } | 157 } |
143 if (FLAG_debug_code && | 158 if (FLAG_debug_code && |
144 (((object_regs |non_object_regs) & (1 << r)) == 0)) { | 159 (((object_regs |non_object_regs) & (1 << r)) == 0)) { |
145 __ mov(reg, Operand(kDebugZapValue)); | 160 __ mov(reg, Operand(kDebugZapValue)); |
146 } | 161 } |
147 } | 162 } |
148 } | 163 } |
149 | 164 |
150 // Don't bother removing padding bytes pushed on the stack | 165 // Don't bother removing padding bytes pushed on the stack |
151 // as the frame is going to be restored right away. | 166 // as the frame is going to be restored right away. |
152 | 167 |
153 // Leave the internal frame. | 168 // Leave the internal frame. |
154 } | 169 } |
155 | 170 |
156 // Now that the break point has been handled, resume normal execution by | 171 // Now that the break point has been handled, resume normal execution by |
157 // jumping to the target address intended by the caller and that was | 172 // jumping to the target address intended by the caller and that was |
158 // overwritten by the address of DebugBreakXXX. | 173 // overwritten by the address of DebugBreakXXX. |
159 ExternalReference after_break_target = | 174 ExternalReference after_break_target = |
160 ExternalReference::debug_after_break_target_address(masm->isolate()); | 175 ExternalReference::debug_after_break_target_address(masm->isolate()); |
161 __ mov(ip, Operand(after_break_target)); | 176 __ mov(ip, Operand(after_break_target)); |
162 __ ldr(ip, MemOperand(ip)); | 177 __ LoadP(ip, MemOperand(ip)); |
163 __ Jump(ip); | 178 __ Jump(ip); |
164 } | 179 } |
165 | 180 |
166 | 181 |
167 void DebugCodegen::GenerateCallICStubDebugBreak(MacroAssembler* masm) { | 182 void DebugCodegen::GenerateCallICStubDebugBreak(MacroAssembler* masm) { |
168 // Register state for CallICStub | 183 // Register state for CallICStub |
169 // ----------- S t a t e ------------- | 184 // ----------- S t a t e ------------- |
170 // -- r1 : function | 185 // -- r4 : function |
171 // -- r3 : slot in feedback array (smi) | 186 // -- r6 : slot in feedback array (smi) |
172 // ----------------------------------- | 187 // ----------------------------------- |
173 Generate_DebugBreakCallHelper(masm, r1.bit() | r3.bit(), 0); | 188 Generate_DebugBreakCallHelper(masm, r4.bit() | r6.bit(), 0); |
174 } | 189 } |
175 | 190 |
176 | 191 |
177 void DebugCodegen::GenerateLoadICDebugBreak(MacroAssembler* masm) { | 192 void DebugCodegen::GenerateLoadICDebugBreak(MacroAssembler* masm) { |
178 // Calling convention for IC load (from ic-arm.cc). | 193 // Calling convention for IC load (from ic-ppc.cc). |
179 Register receiver = LoadIC::ReceiverRegister(); | 194 Register receiver = LoadIC::ReceiverRegister(); |
180 Register name = LoadIC::NameRegister(); | 195 Register name = LoadIC::NameRegister(); |
181 Generate_DebugBreakCallHelper(masm, receiver.bit() | name.bit(), 0); | 196 Generate_DebugBreakCallHelper(masm, receiver.bit() | name.bit(), 0); |
182 } | 197 } |
183 | 198 |
184 | 199 |
185 void DebugCodegen::GenerateStoreICDebugBreak(MacroAssembler* masm) { | 200 void DebugCodegen::GenerateStoreICDebugBreak(MacroAssembler* masm) { |
186 // Calling convention for IC store (from ic-arm.cc). | 201 // Calling convention for IC store (from ic-ppc.cc). |
187 Register receiver = StoreIC::ReceiverRegister(); | 202 Register receiver = StoreIC::ReceiverRegister(); |
188 Register name = StoreIC::NameRegister(); | 203 Register name = StoreIC::NameRegister(); |
189 Register value = StoreIC::ValueRegister(); | 204 Register value = StoreIC::ValueRegister(); |
190 Generate_DebugBreakCallHelper( | 205 Generate_DebugBreakCallHelper( |
191 masm, receiver.bit() | name.bit() | value.bit(), 0); | 206 masm, receiver.bit() | name.bit() | value.bit(), 0); |
192 } | 207 } |
193 | 208 |
194 | 209 |
195 void DebugCodegen::GenerateKeyedLoadICDebugBreak(MacroAssembler* masm) { | 210 void DebugCodegen::GenerateKeyedLoadICDebugBreak(MacroAssembler* masm) { |
196 // Calling convention for keyed IC load (from ic-arm.cc). | 211 // Calling convention for keyed IC load (from ic-ppc.cc). |
197 GenerateLoadICDebugBreak(masm); | 212 GenerateLoadICDebugBreak(masm); |
198 } | 213 } |
199 | 214 |
200 | 215 |
201 void DebugCodegen::GenerateKeyedStoreICDebugBreak(MacroAssembler* masm) { | 216 void DebugCodegen::GenerateKeyedStoreICDebugBreak(MacroAssembler* masm) { |
202 // Calling convention for IC keyed store call (from ic-arm.cc). | 217 // Calling convention for IC keyed store call (from ic-ppc.cc). |
203 Register receiver = KeyedStoreIC::ReceiverRegister(); | 218 Register receiver = KeyedStoreIC::ReceiverRegister(); |
204 Register name = KeyedStoreIC::NameRegister(); | 219 Register name = KeyedStoreIC::NameRegister(); |
205 Register value = KeyedStoreIC::ValueRegister(); | 220 Register value = KeyedStoreIC::ValueRegister(); |
206 Generate_DebugBreakCallHelper( | 221 Generate_DebugBreakCallHelper( |
207 masm, receiver.bit() | name.bit() | value.bit(), 0); | 222 masm, receiver.bit() | name.bit() | value.bit(), 0); |
208 } | 223 } |
209 | 224 |
210 | 225 |
211 void DebugCodegen::GenerateCompareNilICDebugBreak(MacroAssembler* masm) { | 226 void DebugCodegen::GenerateCompareNilICDebugBreak(MacroAssembler* masm) { |
212 // Register state for CompareNil IC | 227 // Register state for CompareNil IC |
213 // ----------- S t a t e ------------- | 228 // ----------- S t a t e ------------- |
214 // -- r0 : value | 229 // -- r3 : value |
215 // ----------------------------------- | 230 // ----------------------------------- |
216 Generate_DebugBreakCallHelper(masm, r0.bit(), 0); | 231 Generate_DebugBreakCallHelper(masm, r3.bit(), 0); |
217 } | 232 } |
218 | 233 |
219 | 234 |
220 void DebugCodegen::GenerateReturnDebugBreak(MacroAssembler* masm) { | 235 void DebugCodegen::GenerateReturnDebugBreak(MacroAssembler* masm) { |
221 // In places other than IC call sites it is expected that r0 is TOS which | 236 // In places other than IC call sites it is expected that r3 is TOS which |
222 // is an object - this is not generally the case so this should be used with | 237 // is an object - this is not generally the case so this should be used with |
223 // care. | 238 // care. |
224 Generate_DebugBreakCallHelper(masm, r0.bit(), 0); | 239 Generate_DebugBreakCallHelper(masm, r3.bit(), 0); |
225 } | 240 } |
226 | 241 |
227 | 242 |
228 void DebugCodegen::GenerateCallFunctionStubDebugBreak(MacroAssembler* masm) { | 243 void DebugCodegen::GenerateCallFunctionStubDebugBreak(MacroAssembler* masm) { |
229 // Register state for CallFunctionStub (from code-stubs-arm.cc). | 244 // Register state for CallFunctionStub (from code-stubs-ppc.cc). |
230 // ----------- S t a t e ------------- | 245 // ----------- S t a t e ------------- |
231 // -- r1 : function | 246 // -- r4 : function |
232 // ----------------------------------- | 247 // ----------------------------------- |
233 Generate_DebugBreakCallHelper(masm, r1.bit(), 0); | 248 Generate_DebugBreakCallHelper(masm, r4.bit(), 0); |
234 } | 249 } |
235 | 250 |
236 | 251 |
237 void DebugCodegen::GenerateCallConstructStubDebugBreak(MacroAssembler* masm) { | 252 void DebugCodegen::GenerateCallConstructStubDebugBreak(MacroAssembler* masm) { |
238 // Calling convention for CallConstructStub (from code-stubs-arm.cc) | 253 // Calling convention for CallConstructStub (from code-stubs-ppc.cc) |
239 // ----------- S t a t e ------------- | 254 // ----------- S t a t e ------------- |
240 // -- r0 : number of arguments (not smi) | 255 // -- r3 : number of arguments (not smi) |
241 // -- r1 : constructor function | 256 // -- r4 : constructor function |
242 // ----------------------------------- | 257 // ----------------------------------- |
243 Generate_DebugBreakCallHelper(masm, r1.bit(), r0.bit()); | 258 Generate_DebugBreakCallHelper(masm, r4.bit(), r3.bit()); |
244 } | 259 } |
245 | 260 |
246 | 261 |
247 void DebugCodegen::GenerateCallConstructStubRecordDebugBreak( | 262 void DebugCodegen::GenerateCallConstructStubRecordDebugBreak( |
248 MacroAssembler* masm) { | 263 MacroAssembler* masm) { |
249 // Calling convention for CallConstructStub (from code-stubs-arm.cc) | 264 // Calling convention for CallConstructStub (from code-stubs-ppc.cc) |
250 // ----------- S t a t e ------------- | 265 // ----------- S t a t e ------------- |
251 // -- r0 : number of arguments (not smi) | 266 // -- r3 : number of arguments (not smi) |
252 // -- r1 : constructor function | 267 // -- r4 : constructor function |
253 // -- r2 : feedback array | 268 // -- r5 : feedback array |
254 // -- r3 : feedback slot (smi) | 269 // -- r6 : feedback slot (smi) |
255 // ----------------------------------- | 270 // ----------------------------------- |
256 Generate_DebugBreakCallHelper(masm, r1.bit() | r2.bit() | r3.bit(), r0.bit()); | 271 Generate_DebugBreakCallHelper(masm, r4.bit() | r5.bit() | r6.bit(), r3.bit()); |
257 } | 272 } |
258 | 273 |
259 | 274 |
260 void DebugCodegen::GenerateSlot(MacroAssembler* masm) { | 275 void DebugCodegen::GenerateSlot(MacroAssembler* masm) { |
261 // Generate enough nop's to make space for a call instruction. Avoid emitting | 276 // Generate enough nop's to make space for a call instruction. Avoid emitting |
262 // the constant pool in the debug break slot code. | 277 // the trampoline pool in the debug break slot code. |
263 Assembler::BlockConstPoolScope block_const_pool(masm); | 278 Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm); |
264 Label check_codesize; | 279 Label check_codesize; |
265 __ bind(&check_codesize); | 280 __ bind(&check_codesize); |
266 __ RecordDebugBreakSlot(); | 281 __ RecordDebugBreakSlot(); |
267 for (int i = 0; i < Assembler::kDebugBreakSlotInstructions; i++) { | 282 for (int i = 0; i < Assembler::kDebugBreakSlotInstructions; i++) { |
268 __ nop(MacroAssembler::DEBUG_BREAK_NOP); | 283 __ nop(MacroAssembler::DEBUG_BREAK_NOP); |
269 } | 284 } |
270 ASSERT_EQ(Assembler::kDebugBreakSlotInstructions, | 285 ASSERT_EQ(Assembler::kDebugBreakSlotInstructions, |
271 masm->InstructionsGeneratedSince(&check_codesize)); | 286 masm->InstructionsGeneratedSince(&check_codesize)); |
272 } | 287 } |
273 | 288 |
274 | 289 |
275 void DebugCodegen::GenerateSlotDebugBreak(MacroAssembler* masm) { | 290 void DebugCodegen::GenerateSlotDebugBreak(MacroAssembler* masm) { |
276 // In the places where a debug break slot is inserted no registers can contain | 291 // In the places where a debug break slot is inserted no registers can contain |
277 // object pointers. | 292 // object pointers. |
278 Generate_DebugBreakCallHelper(masm, 0, 0); | 293 Generate_DebugBreakCallHelper(masm, 0, 0); |
279 } | 294 } |
280 | 295 |
281 | 296 |
282 void DebugCodegen::GeneratePlainReturnLiveEdit(MacroAssembler* masm) { | 297 void DebugCodegen::GeneratePlainReturnLiveEdit(MacroAssembler* masm) { |
283 __ Ret(); | 298 __ Ret(); |
284 } | 299 } |
285 | 300 |
286 | 301 |
287 void DebugCodegen::GenerateFrameDropperLiveEdit(MacroAssembler* masm) { | 302 void DebugCodegen::GenerateFrameDropperLiveEdit(MacroAssembler* masm) { |
288 ExternalReference restarter_frame_function_slot = | 303 ExternalReference restarter_frame_function_slot = |
289 ExternalReference::debug_restarter_frame_function_pointer_address( | 304 ExternalReference::debug_restarter_frame_function_pointer_address( |
290 masm->isolate()); | 305 masm->isolate()); |
291 __ mov(ip, Operand(restarter_frame_function_slot)); | 306 __ mov(ip, Operand(restarter_frame_function_slot)); |
292 __ mov(r1, Operand::Zero()); | 307 __ li(r4, Operand::Zero()); |
293 __ str(r1, MemOperand(ip, 0)); | 308 __ StoreP(r4, MemOperand(ip, 0)); |
294 | 309 |
295 // Load the function pointer off of our current stack frame. | 310 // Load the function pointer off of our current stack frame. |
296 __ ldr(r1, MemOperand(fp, | 311 __ LoadP(r4, MemOperand(fp, |
297 StandardFrameConstants::kConstantPoolOffset - kPointerSize)); | 312 StandardFrameConstants::kConstantPoolOffset - kPointerSize)); |
298 | 313 |
299 // Pop return address, frame and constant pool pointer (if | 314 // Pop return address, frame and constant pool pointer (if |
300 // FLAG_enable_ool_constant_pool). | 315 // FLAG_enable_ool_constant_pool). |
301 __ LeaveFrame(StackFrame::INTERNAL); | 316 __ LeaveFrame(StackFrame::INTERNAL); |
302 | 317 |
303 { ConstantPoolUnavailableScope constant_pool_unavailable(masm); | 318 // Load context from the function. |
304 // Load context from the function. | 319 __ LoadP(cp, FieldMemOperand(r4, JSFunction::kContextOffset)); |
305 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); | |
306 | 320 |
307 // Get function code. | 321 // Get function code. |
308 __ ldr(ip, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); | 322 __ LoadP(ip, FieldMemOperand(r4, JSFunction::kSharedFunctionInfoOffset)); |
309 __ ldr(ip, FieldMemOperand(ip, SharedFunctionInfo::kCodeOffset)); | 323 __ LoadP(ip, FieldMemOperand(ip, SharedFunctionInfo::kCodeOffset)); |
310 __ add(ip, ip, Operand(Code::kHeaderSize - kHeapObjectTag)); | 324 __ addi(ip, ip, Operand(Code::kHeaderSize - kHeapObjectTag)); |
311 | 325 |
312 // Re-run JSFunction, r1 is function, cp is context. | 326 // Re-run JSFunction, r4 is function, cp is context. |
313 __ Jump(ip); | 327 __ Jump(ip); |
314 } | |
315 } | 328 } |
316 | 329 |
317 | 330 |
318 const bool LiveEdit::kFrameDropperSupported = true; | 331 const bool LiveEdit::kFrameDropperSupported = true; |
319 | 332 |
320 #undef __ | 333 #undef __ |
321 | 334 |
322 } } // namespace v8::internal | 335 } } // namespace v8::internal |
323 | 336 |
324 #endif // V8_TARGET_ARCH_ARM | 337 #endif // V8_TARGET_ARCH_PPC |
OLD | NEW |