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/codegen.h" 8 #include "src/debug/debug.h" 9 10 namespace v8 { 11 namespace internal { 12 13 #define __ ACCESS_MASM(masm) 14 15 16 void EmitDebugBreakSlot(MacroAssembler* masm) { 17 Label check_size; 18 __ bind(&check_size); 19 for (int i = 0; i < Assembler::kDebugBreakSlotInstructions; i++) { 20 __ nop(MacroAssembler::DEBUG_BREAK_NOP); 21 } 22 DCHECK_EQ(Assembler::kDebugBreakSlotInstructions, 23 masm->InstructionsGeneratedSince(&check_size)); 24 } 25 26 27 void DebugCodegen::GenerateSlot(MacroAssembler* masm, RelocInfo::Mode mode) { 28 // Generate enough nop's to make space for a call instruction. Avoid emitting 29 // the trampoline pool in the debug break slot code. 30 Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm); 31 masm->RecordDebugBreakSlot(mode); 32 EmitDebugBreakSlot(masm); 33 } 34 35 36 void DebugCodegen::ClearDebugBreakSlot(Isolate* isolate, Address pc) { 37 CodePatcher patcher(isolate, pc, Assembler::kDebugBreakSlotInstructions); 38 EmitDebugBreakSlot(patcher.masm()); 39 } 40 41 42 void DebugCodegen::PatchDebugBreakSlot(Isolate* isolate, Address pc, 43 Handle<Code> code) { 44 DCHECK_EQ(Code::BUILTIN, code->kind()); 45 CodePatcher patcher(isolate, pc, Assembler::kDebugBreakSlotInstructions); 46 // Patch the code changing the debug break slot code from 47 // 48 // ori r3, r3, 0 49 // ori r3, r3, 0 50 // ori r3, r3, 0 51 // ori r3, r3, 0 52 // ori r3, r3, 0 53 // 54 // to a call to the debug break code, using a FIXED_SEQUENCE. 55 // 56 // mov r0, <address> 57 // mtlr r0 58 // blrl 59 // 60 Assembler::BlockTrampolinePoolScope block_trampoline_pool(patcher.masm()); 61 patcher.masm()->mov(v8::internal::r0, 62 Operand(reinterpret_cast<intptr_t>(code->entry()))); 63 patcher.masm()->mtctr(v8::internal::r0); 64 patcher.masm()->bctrl(); 65 } 66 67 68 void DebugCodegen::GenerateDebugBreakStub(MacroAssembler* masm, 69 DebugBreakCallHelperMode mode) { 70 __ RecordComment("Debug break"); 71 { 72 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); 73 74 // Load padding words on stack. 75 __ LoadSmiLiteral(ip, Smi::FromInt(LiveEdit::kFramePaddingValue)); 76 for (int i = 0; i < LiveEdit::kFramePaddingInitialSize; i++) { 77 __ push(ip); 78 } 79 __ LoadSmiLiteral(ip, Smi::FromInt(LiveEdit::kFramePaddingInitialSize)); 80 __ push(ip); 81 82 if (mode == SAVE_RESULT_REGISTER) __ push(r3); 83 84 __ mov(r3, Operand::Zero()); // no arguments 85 __ mov(r4, 86 Operand(ExternalReference( 87 Runtime::FunctionForId(Runtime::kDebugBreak), masm->isolate()))); 88 89 CEntryStub ceb(masm->isolate(), 1); 90 __ CallStub(&ceb); 91 92 if (FLAG_debug_code) { 93 for (int i = 0; i < kNumJSCallerSaved; i++) { 94 Register reg = {JSCallerSavedCode(i)}; 95 __ mov(reg, Operand(kDebugZapValue)); 96 } 97 } 98 99 if (mode == SAVE_RESULT_REGISTER) __ pop(r3); 100 101 // Don't bother removing padding bytes pushed on the stack 102 // as the frame is going to be restored right away. 103 104 // Leave the internal frame. 105 } 106 107 // Now that the break point has been handled, resume normal execution by 108 // jumping to the target address intended by the caller and that was 109 // overwritten by the address of DebugBreakXXX. 110 ExternalReference after_break_target = 111 ExternalReference::debug_after_break_target_address(masm->isolate()); 112 __ mov(ip, Operand(after_break_target)); 113 __ LoadP(ip, MemOperand(ip)); 114 __ JumpToJSEntry(ip); 115 } 116 117 118 void DebugCodegen::GenerateFrameDropperLiveEdit(MacroAssembler* masm) { 119 // Load the function pointer off of our current stack frame. 120 __ LoadP(r4, MemOperand(fp, StandardFrameConstants::kConstantPoolOffset - 121 kPointerSize)); 122 123 // Pop return address and frame 124 __ LeaveFrame(StackFrame::INTERNAL); 125 126 ParameterCount dummy(0); 127 __ FloodFunctionIfStepping(r4, no_reg, dummy, dummy); 128 129 // Load context from the function. 130 __ LoadP(cp, FieldMemOperand(r4, JSFunction::kContextOffset)); 131 132 // Clear new.target as a safety measure. 133 __ LoadRoot(r6, Heap::kUndefinedValueRootIndex); 134 135 // Get function code. 136 __ LoadP(ip, FieldMemOperand(r4, JSFunction::kSharedFunctionInfoOffset)); 137 __ LoadP(ip, FieldMemOperand(ip, SharedFunctionInfo::kCodeOffset)); 138 __ addi(ip, ip, Operand(Code::kHeaderSize - kHeapObjectTag)); 139 140 // Re-run JSFunction, r4 is function, cp is context. 141 __ Jump(ip); 142 } 143 144 145 const bool LiveEdit::kFrameDropperSupported = true; 146 147 #undef __ 148 } // namespace internal 149 } // namespace v8 150 151 #endif // V8_TARGET_ARCH_PPC 152