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