1 // Copyright 2015 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 #include "src/v8.h" 6 7 #if V8_TARGET_ARCH_S390 8 9 #include "src/debug/debug.h" 10 11 #include "src/codegen.h" 12 #include "src/debug/liveedit.h" 13 14 namespace v8 { 15 namespace internal { 16 17 #define __ ACCESS_MASM(masm) 18 19 void EmitDebugBreakSlot(MacroAssembler* masm) { 20 Label check_size; 21 __ bind(&check_size); 22 // oill r3, 0 23 // oill r3, 0 24 __ nop(Assembler::DEBUG_BREAK_NOP); 25 __ nop(Assembler::DEBUG_BREAK_NOP); 26 27 // lr r0, r0 64-bit only 28 // lr r0, r0 64-bit only 29 // lr r0, r0 64-bit only 30 for (int i = 8; i < Assembler::kDebugBreakSlotLength; i += 2) { 31 __ nop(); 32 } 33 DCHECK_EQ(Assembler::kDebugBreakSlotLength, 34 masm->SizeOfCodeGeneratedSince(&check_size)); 35 } 36 37 void DebugCodegen::GenerateSlot(MacroAssembler* masm, RelocInfo::Mode mode) { 38 // Generate enough nop's to make space for a call instruction. 39 masm->RecordDebugBreakSlot(mode); 40 EmitDebugBreakSlot(masm); 41 } 42 43 void DebugCodegen::ClearDebugBreakSlot(Isolate* isolate, Address pc) { 44 CodePatcher patcher(isolate, pc, Assembler::kDebugBreakSlotLength); 45 EmitDebugBreakSlot(patcher.masm()); 46 } 47 48 void DebugCodegen::PatchDebugBreakSlot(Isolate* isolate, Address pc, 49 Handle<Code> code) { 50 DCHECK(code->is_debug_stub()); 51 CodePatcher patcher(isolate, pc, Assembler::kDebugBreakSlotLength); 52 // Patch the code changing the debug break slot code from 53 // 54 // oill r3, 0 55 // oill r3, 0 56 // oill r3, 0 64-bit only 57 // lr r0, r0 64-bit only 58 // 59 // to a call to the debug break code, using a FIXED_SEQUENCE. 60 // 61 // iilf r14, <address> 6-bytes 62 // basr r14, r14A 2-bytes 63 // 64 // The 64bit sequence has an extra iihf. 65 // 66 // iihf r14, <high 32-bits address> 6-bytes 67 // iilf r14, <lower 32-bits address> 6-bytes 68 // basr r14, r14 2-bytes 69 patcher.masm()->mov(v8::internal::r14, 70 Operand(reinterpret_cast<intptr_t>(code->entry()))); 71 patcher.masm()->basr(v8::internal::r14, v8::internal::r14); 72 } 73 74 bool DebugCodegen::DebugBreakSlotIsPatched(Address pc) { 75 Instr current_instr = Assembler::instr_at(pc); 76 return !Assembler::IsNop(current_instr, Assembler::DEBUG_BREAK_NOP); 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(r2); 89 } else { 90 // Non-return breaks. 91 __ Push(masm->isolate()->factory()->the_hole_value()); 92 } 93 __ mov(r2, Operand(1)); 94 __ mov(r3, 95 Operand(ExternalReference( 96 Runtime::FunctionForId(Runtime::kDebugBreak), masm->isolate()))); 97 98 CEntryStub ceb(masm->isolate(), 1); 99 __ CallStub(&ceb); 100 101 if (FLAG_debug_code) { 102 for (int i = 0; i < kNumJSCallerSaved; i++) { 103 Register reg = {JSCallerSavedCode(i)}; 104 // Do not clobber r2 if mode is SAVE_RESULT_REGISTER. It will 105 // contain return value of the function. 106 if (!(reg.is(r2) && (mode == SAVE_RESULT_REGISTER))) { 107 __ mov(reg, Operand(kDebugZapValue)); 108 } 109 } 110 } 111 // Leave the internal frame. 112 } 113 __ MaybeDropFrames(); 114 115 // Return to caller. 116 __ Ret(); 117 } 118 119 void DebugCodegen::GenerateHandleDebuggerStatement(MacroAssembler* masm) { 120 { 121 FrameScope scope(masm, StackFrame::INTERNAL); 122 __ CallRuntime(Runtime::kHandleDebuggerStatement, 0); 123 } 124 __ MaybeDropFrames(); 125 126 // Return to caller. 127 __ Ret(); 128 } 129 130 void DebugCodegen::GenerateFrameDropperTrampoline(MacroAssembler* masm) { 131 // Frame is being dropped: 132 // - Drop to the target frame specified by r3. 133 // - Look up current function on the frame. 134 // - Leave the frame. 135 // - Restart the frame by calling the function. 136 137 __ LoadRR(fp, r3); 138 __ LoadP(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); 139 __ LeaveFrame(StackFrame::INTERNAL); 140 __ LoadP(r2, FieldMemOperand(r3, JSFunction::kSharedFunctionInfoOffset)); 141 __ LoadP( 142 r2, FieldMemOperand(r2, SharedFunctionInfo::kFormalParameterCountOffset)); 143 __ LoadRR(r4, r2); 144 145 ParameterCount dummy1(r4); 146 ParameterCount dummy2(r2); 147 __ InvokeFunction(r3, dummy1, dummy2, JUMP_FUNCTION, 148 CheckDebugStepCallWrapper()); 149 } 150 151 const bool LiveEdit::kFrameDropperSupported = true; 152 153 #undef __ 154 } // namespace internal 155 } // namespace v8 156 157 #endif // V8_TARGET_ARCH_S390 158