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 3 // found in the LICENSE file. 4 5 #if V8_TARGET_ARCH_MIPS64 6 7 #include "src/debug/debug.h" 8 9 #include "src/codegen.h" 10 #include "src/debug/liveedit.h" 11 12 namespace v8 { 13 namespace internal { 14 15 #define __ ACCESS_MASM(masm) 16 17 void EmitDebugBreakSlot(MacroAssembler* masm) { 18 Label check_size; 19 __ bind(&check_size); 20 for (int i = 0; i < Assembler::kDebugBreakSlotInstructions; i++) { 21 __ nop(MacroAssembler::DEBUG_BREAK_NOP); 22 } 23 DCHECK_EQ(Assembler::kDebugBreakSlotInstructions, 24 masm->InstructionsGeneratedSince(&check_size)); 25 } 26 27 28 void DebugCodegen::GenerateSlot(MacroAssembler* masm, RelocInfo::Mode mode) { 29 // Generate enough nop's to make space for a call instruction. Avoid emitting 30 // the trampoline pool in the debug break slot code. 31 Assembler::BlockTrampolinePoolScope block_pool(masm); 32 masm->RecordDebugBreakSlot(mode); 33 EmitDebugBreakSlot(masm); 34 } 35 36 37 void DebugCodegen::ClearDebugBreakSlot(Isolate* isolate, Address pc) { 38 CodePatcher patcher(isolate, pc, Assembler::kDebugBreakSlotInstructions); 39 EmitDebugBreakSlot(patcher.masm()); 40 } 41 42 43 void DebugCodegen::PatchDebugBreakSlot(Isolate* isolate, Address pc, 44 Handle<Code> code) { 45 DCHECK(code->is_debug_stub()); 46 CodePatcher patcher(isolate, pc, Assembler::kDebugBreakSlotInstructions); 47 // Patch the code changing the debug break slot code from: 48 // nop(DEBUG_BREAK_NOP) - nop(1) is sll(zero_reg, zero_reg, 1) 49 // nop(DEBUG_BREAK_NOP) 50 // nop(DEBUG_BREAK_NOP) 51 // nop(DEBUG_BREAK_NOP) 52 // nop(DEBUG_BREAK_NOP) 53 // nop(DEBUG_BREAK_NOP) 54 // to a call to the debug break slot code. 55 // li t9, address (4-instruction sequence on mips64) 56 // call t9 (jalr t9 / nop instruction pair) 57 patcher.masm()->li(v8::internal::t9, 58 Operand(reinterpret_cast<int64_t>(code->entry())), 59 ADDRESS_LOAD); 60 patcher.masm()->Call(v8::internal::t9); 61 } 62 63 bool DebugCodegen::DebugBreakSlotIsPatched(Address pc) { 64 Instr current_instr = Assembler::instr_at(pc); 65 return !Assembler::IsNop(current_instr, Assembler::DEBUG_BREAK_NOP); 66 } 67 68 void DebugCodegen::GenerateHandleDebuggerStatement(MacroAssembler* masm) { 69 { 70 FrameScope scope(masm, StackFrame::INTERNAL); 71 __ CallRuntime(Runtime::kHandleDebuggerStatement, 0); 72 } 73 __ MaybeDropFrames(); 74 75 // Return to caller. 76 __ Ret(); 77 } 78 79 void DebugCodegen::GenerateDebugBreakStub(MacroAssembler* masm, 80 DebugBreakCallHelperMode mode) { 81 __ RecordComment("Debug break"); 82 { 83 FrameScope scope(masm, StackFrame::INTERNAL); 84 85 // Push arguments for DebugBreak call. 86 if (mode == SAVE_RESULT_REGISTER) { 87 // Break on return. 88 __ push(v0); 89 } else { 90 // Non-return breaks. 91 __ Push(masm->isolate()->factory()->the_hole_value()); 92 } 93 __ PrepareCEntryArgs(1); 94 __ PrepareCEntryFunction(ExternalReference( 95 Runtime::FunctionForId(Runtime::kDebugBreak), masm->isolate())); 96 97 CEntryStub ceb(masm->isolate(), 1); 98 __ CallStub(&ceb); 99 100 if (FLAG_debug_code) { 101 for (int i = 0; i < kNumJSCallerSaved; i++) { 102 Register reg = {JSCallerSavedCode(i)}; 103 // Do not clobber v0 if mode is SAVE_RESULT_REGISTER. It will 104 // contain return value of the function returned by DebugBreak. 105 if (!(reg.is(v0) && (mode == SAVE_RESULT_REGISTER))) { 106 __ li(reg, kDebugZapValue); 107 } 108 } 109 } 110 111 // Leave the internal frame. 112 } 113 114 __ MaybeDropFrames(); 115 116 // Return to caller. 117 __ Ret(); 118 } 119 120 void DebugCodegen::GenerateFrameDropperTrampoline(MacroAssembler* masm) { 121 // Frame is being dropped: 122 // - Drop to the target frame specified by a1. 123 // - Look up current function on the frame. 124 // - Leave the frame. 125 // - Restart the frame by calling the function. 126 __ mov(fp, a1); 127 __ ld(a1, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); 128 129 // Pop return address and frame. 130 __ LeaveFrame(StackFrame::INTERNAL); 131 132 __ ld(a0, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset)); 133 __ ld(a0, 134 FieldMemOperand(a0, SharedFunctionInfo::kFormalParameterCountOffset)); 135 __ mov(a2, a0); 136 137 ParameterCount dummy1(a2); 138 ParameterCount dummy2(a0); 139 __ InvokeFunction(a1, dummy1, dummy2, JUMP_FUNCTION, 140 CheckDebugStepCallWrapper()); 141 } 142 143 144 const bool LiveEdit::kFrameDropperSupported = true; 145 146 #undef __ 147 148 } // namespace internal 149 } // namespace v8 150 151 #endif // V8_TARGET_ARCH_MIPS64 152