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