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