| OLD | NEW |
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 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_PPC | 7 #if V8_TARGET_ARCH_PPC |
| 8 | 8 |
| 9 #include "src/codegen.h" | 9 #include "src/codegen.h" |
| 10 #include "src/debug.h" | 10 #include "src/debug.h" |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 64 debug_info_->GetIsolate()->builtins()->Slot_DebugBreak()->entry()))); | 64 debug_info_->GetIsolate()->builtins()->Slot_DebugBreak()->entry()))); |
| 65 patcher.masm()->mtctr(v8::internal::r0); | 65 patcher.masm()->mtctr(v8::internal::r0); |
| 66 patcher.masm()->bctrl(); | 66 patcher.masm()->bctrl(); |
| 67 } | 67 } |
| 68 | 68 |
| 69 | 69 |
| 70 #define __ ACCESS_MASM(masm) | 70 #define __ ACCESS_MASM(masm) |
| 71 | 71 |
| 72 | 72 |
| 73 static void Generate_DebugBreakCallHelper(MacroAssembler* masm, | 73 static void Generate_DebugBreakCallHelper(MacroAssembler* masm, |
| 74 RegList object_regs, | 74 RegList object_regs) { |
| 75 RegList non_object_regs) { | |
| 76 { | 75 { |
| 77 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); | 76 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); |
| 78 | 77 |
| 79 // Load padding words on stack. | 78 // Load padding words on stack. |
| 80 __ LoadSmiLiteral(ip, Smi::FromInt(LiveEdit::kFramePaddingValue)); | 79 __ LoadSmiLiteral(ip, Smi::FromInt(LiveEdit::kFramePaddingValue)); |
| 81 for (int i = 0; i < LiveEdit::kFramePaddingInitialSize; i++) { | 80 for (int i = 0; i < LiveEdit::kFramePaddingInitialSize; i++) { |
| 82 __ push(ip); | 81 __ push(ip); |
| 83 } | 82 } |
| 84 __ LoadSmiLiteral(ip, Smi::FromInt(LiveEdit::kFramePaddingInitialSize)); | 83 __ LoadSmiLiteral(ip, Smi::FromInt(LiveEdit::kFramePaddingInitialSize)); |
| 85 __ push(ip); | 84 __ push(ip); |
| 86 | 85 |
| 87 // Store the registers containing live values on the expression stack to | 86 // Store the registers containing live values on the expression stack to |
| 88 // make sure that these are correctly updated during GC. Non object values | 87 // make sure that these are correctly updated during GC. Non object values |
| 89 // are stored as a smi causing it to be untouched by GC. | 88 // are stored as a smi causing it to be untouched by GC. |
| 90 DCHECK((object_regs & ~kJSCallerSaved) == 0); | 89 DCHECK((object_regs & ~kJSCallerSaved) == 0); |
| 91 DCHECK((non_object_regs & ~kJSCallerSaved) == 0); | 90 if (object_regs != 0) { |
| 92 DCHECK((object_regs & non_object_regs) == 0); | 91 __ MultiPush(object_regs); |
| 93 if ((object_regs | non_object_regs) != 0) { | |
| 94 for (int i = 0; i < kNumJSCallerSaved; i++) { | |
| 95 int r = JSCallerSavedCode(i); | |
| 96 Register reg = {r}; | |
| 97 if ((non_object_regs & (1 << r)) != 0) { | |
| 98 if (FLAG_debug_code) { | |
| 99 __ TestUnsignedSmiCandidate(reg, r0); | |
| 100 __ Assert(eq, kUnableToEncodeValueAsSmi, cr0); | |
| 101 } | |
| 102 __ SmiTag(reg); | |
| 103 } | |
| 104 } | |
| 105 __ MultiPush(object_regs | non_object_regs); | |
| 106 } | 92 } |
| 107 | 93 |
| 108 #ifdef DEBUG | 94 #ifdef DEBUG |
| 109 __ RecordComment("// Calling from debug break to runtime - come in - over"); | 95 __ RecordComment("// Calling from debug break to runtime - come in - over"); |
| 110 #endif | 96 #endif |
| 111 __ mov(r3, Operand::Zero()); // no arguments | 97 __ mov(r3, Operand::Zero()); // no arguments |
| 112 __ mov(r4, Operand(ExternalReference::debug_break(masm->isolate()))); | 98 __ mov(r4, Operand(ExternalReference::debug_break(masm->isolate()))); |
| 113 | 99 |
| 114 CEntryStub ceb(masm->isolate(), 1); | 100 CEntryStub ceb(masm->isolate(), 1); |
| 115 __ CallStub(&ceb); | 101 __ CallStub(&ceb); |
| 116 | 102 |
| 117 // Restore the register values from the expression stack. | 103 // Restore the register values from the expression stack. |
| 118 if ((object_regs | non_object_regs) != 0) { | 104 if (object_regs != 0) { |
| 119 __ MultiPop(object_regs | non_object_regs); | 105 __ MultiPop(object_regs); |
| 120 for (int i = 0; i < kNumJSCallerSaved; i++) { | 106 } |
| 121 int r = JSCallerSavedCode(i); | 107 |
| 122 Register reg = {r}; | 108 for (int i = 0; i < kNumJSCallerSaved; i++) { |
| 123 if ((non_object_regs & (1 << r)) != 0) { | 109 int r = JSCallerSavedCode(i); |
| 124 __ SmiUntag(reg); | 110 Register reg = {r}; |
| 125 } | 111 if (FLAG_debug_code && ((object_regs & (1 << r)) == 0)) { |
| 126 if (FLAG_debug_code && | 112 __ mov(reg, Operand(kDebugZapValue)); |
| 127 (((object_regs | non_object_regs) & (1 << r)) == 0)) { | |
| 128 __ mov(reg, Operand(kDebugZapValue)); | |
| 129 } | |
| 130 } | 113 } |
| 131 } | 114 } |
| 132 | 115 |
| 133 // Don't bother removing padding bytes pushed on the stack | 116 // Don't bother removing padding bytes pushed on the stack |
| 134 // as the frame is going to be restored right away. | 117 // as the frame is going to be restored right away. |
| 135 | 118 |
| 136 // Leave the internal frame. | 119 // Leave the internal frame. |
| 137 } | 120 } |
| 138 | 121 |
| 139 // Now that the break point has been handled, resume normal execution by | 122 // Now that the break point has been handled, resume normal execution by |
| 140 // jumping to the target address intended by the caller and that was | 123 // jumping to the target address intended by the caller and that was |
| 141 // overwritten by the address of DebugBreakXXX. | 124 // overwritten by the address of DebugBreakXXX. |
| 142 ExternalReference after_break_target = | 125 ExternalReference after_break_target = |
| 143 ExternalReference::debug_after_break_target_address(masm->isolate()); | 126 ExternalReference::debug_after_break_target_address(masm->isolate()); |
| 144 __ mov(ip, Operand(after_break_target)); | 127 __ mov(ip, Operand(after_break_target)); |
| 145 __ LoadP(ip, MemOperand(ip)); | 128 __ LoadP(ip, MemOperand(ip)); |
| 146 __ JumpToJSEntry(ip); | 129 __ JumpToJSEntry(ip); |
| 147 } | 130 } |
| 148 | 131 |
| 149 | 132 |
| 150 void DebugCodegen::GenerateCallICStubDebugBreak(MacroAssembler* masm) { | |
| 151 // Register state for CallICStub | |
| 152 // ----------- S t a t e ------------- | |
| 153 // -- r4 : function | |
| 154 // -- r6 : slot in feedback array (smi) | |
| 155 // ----------------------------------- | |
| 156 Generate_DebugBreakCallHelper(masm, r4.bit() | r6.bit(), 0); | |
| 157 } | |
| 158 | |
| 159 | |
| 160 void DebugCodegen::GenerateReturnDebugBreak(MacroAssembler* masm) { | 133 void DebugCodegen::GenerateReturnDebugBreak(MacroAssembler* masm) { |
| 161 // In places other than IC call sites it is expected that r3 is TOS which | 134 // In places other than IC call sites it is expected that r3 is TOS which |
| 162 // is an object - this is not generally the case so this should be used with | 135 // is an object - this is not generally the case so this should be used with |
| 163 // care. | 136 // care. |
| 164 Generate_DebugBreakCallHelper(masm, r3.bit(), 0); | 137 Generate_DebugBreakCallHelper(masm, r3.bit()); |
| 165 } | 138 } |
| 166 | 139 |
| 167 | 140 |
| 168 void DebugCodegen::GenerateCallFunctionStubDebugBreak(MacroAssembler* masm) { | |
| 169 // Register state for CallFunctionStub (from code-stubs-ppc.cc). | |
| 170 // ----------- S t a t e ------------- | |
| 171 // -- r4 : function | |
| 172 // ----------------------------------- | |
| 173 Generate_DebugBreakCallHelper(masm, r4.bit(), 0); | |
| 174 } | |
| 175 | |
| 176 | |
| 177 void DebugCodegen::GenerateCallConstructStubDebugBreak(MacroAssembler* masm) { | |
| 178 // Calling convention for CallConstructStub (from code-stubs-ppc.cc) | |
| 179 // ----------- S t a t e ------------- | |
| 180 // -- r3 : number of arguments (not smi) | |
| 181 // -- r4 : constructor function | |
| 182 // ----------------------------------- | |
| 183 Generate_DebugBreakCallHelper(masm, r4.bit(), r3.bit()); | |
| 184 } | |
| 185 | |
| 186 | |
| 187 void DebugCodegen::GenerateCallConstructStubRecordDebugBreak( | |
| 188 MacroAssembler* masm) { | |
| 189 // Calling convention for CallConstructStub (from code-stubs-ppc.cc) | |
| 190 // ----------- S t a t e ------------- | |
| 191 // -- r3 : number of arguments (not smi) | |
| 192 // -- r4 : constructor function | |
| 193 // -- r5 : feedback array | |
| 194 // -- r6 : feedback slot (smi) | |
| 195 // ----------------------------------- | |
| 196 Generate_DebugBreakCallHelper(masm, r4.bit() | r5.bit() | r6.bit(), r3.bit()); | |
| 197 } | |
| 198 | |
| 199 | |
| 200 void DebugCodegen::GenerateSlot(MacroAssembler* masm) { | 141 void DebugCodegen::GenerateSlot(MacroAssembler* masm) { |
| 201 // Generate enough nop's to make space for a call instruction. Avoid emitting | 142 // Generate enough nop's to make space for a call instruction. Avoid emitting |
| 202 // the trampoline pool in the debug break slot code. | 143 // the trampoline pool in the debug break slot code. |
| 203 Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm); | 144 Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm); |
| 204 Label check_codesize; | 145 Label check_codesize; |
| 205 __ bind(&check_codesize); | 146 __ bind(&check_codesize); |
| 206 __ RecordDebugBreakSlot(); | |
| 207 for (int i = 0; i < Assembler::kDebugBreakSlotInstructions; i++) { | 147 for (int i = 0; i < Assembler::kDebugBreakSlotInstructions; i++) { |
| 208 __ nop(MacroAssembler::DEBUG_BREAK_NOP); | 148 __ nop(MacroAssembler::DEBUG_BREAK_NOP); |
| 209 } | 149 } |
| 210 DCHECK_EQ(Assembler::kDebugBreakSlotInstructions, | 150 DCHECK_EQ(Assembler::kDebugBreakSlotInstructions, |
| 211 masm->InstructionsGeneratedSince(&check_codesize)); | 151 masm->InstructionsGeneratedSince(&check_codesize)); |
| 212 } | 152 } |
| 213 | 153 |
| 214 | 154 |
| 215 void DebugCodegen::GenerateSlotDebugBreak(MacroAssembler* masm) { | 155 void DebugCodegen::GenerateSlotDebugBreak(MacroAssembler* masm) { |
| 216 // In the places where a debug break slot is inserted no registers can contain | 156 // In the places where a debug break slot is inserted no registers can contain |
| 217 // object pointers. | 157 // object pointers. |
| 218 Generate_DebugBreakCallHelper(masm, 0, 0); | 158 Generate_DebugBreakCallHelper(masm, 0); |
| 219 } | 159 } |
| 220 | 160 |
| 221 | 161 |
| 222 void DebugCodegen::GeneratePlainReturnLiveEdit(MacroAssembler* masm) { | 162 void DebugCodegen::GeneratePlainReturnLiveEdit(MacroAssembler* masm) { |
| 223 __ Ret(); | 163 __ Ret(); |
| 224 } | 164 } |
| 225 | 165 |
| 226 | 166 |
| 227 void DebugCodegen::GenerateFrameDropperLiveEdit(MacroAssembler* masm) { | 167 void DebugCodegen::GenerateFrameDropperLiveEdit(MacroAssembler* masm) { |
| 228 ExternalReference restarter_frame_function_slot = | 168 ExternalReference restarter_frame_function_slot = |
| (...skipping 23 matching lines...) Expand all Loading... |
| 252 } | 192 } |
| 253 | 193 |
| 254 | 194 |
| 255 const bool LiveEdit::kFrameDropperSupported = true; | 195 const bool LiveEdit::kFrameDropperSupported = true; |
| 256 | 196 |
| 257 #undef __ | 197 #undef __ |
| 258 } // namespace internal | 198 } // namespace internal |
| 259 } // namespace v8 | 199 } // namespace v8 |
| 260 | 200 |
| 261 #endif // V8_TARGET_ARCH_PPC | 201 #endif // V8_TARGET_ARCH_PPC |
| OLD | NEW |