11b268ca467c924004286c97bac133db489cf43d0Ben Murdoch// Copyright 2015 the V8 project authors. All rights reserved. 21b268ca467c924004286c97bac133db489cf43d0Ben Murdoch// Use of this source code is governed by a BSD-style license that can be 31b268ca467c924004286c97bac133db489cf43d0Ben Murdoch// found in the LICENSE file. 41b268ca467c924004286c97bac133db489cf43d0Ben Murdoch 51b268ca467c924004286c97bac133db489cf43d0Ben Murdoch#include "src/v8.h" 61b268ca467c924004286c97bac133db489cf43d0Ben Murdoch 71b268ca467c924004286c97bac133db489cf43d0Ben Murdoch#if V8_TARGET_ARCH_S390 81b268ca467c924004286c97bac133db489cf43d0Ben Murdoch 91b268ca467c924004286c97bac133db489cf43d0Ben Murdoch#include "src/codegen.h" 101b268ca467c924004286c97bac133db489cf43d0Ben Murdoch#include "src/debug/debug.h" 111b268ca467c924004286c97bac133db489cf43d0Ben Murdoch 121b268ca467c924004286c97bac133db489cf43d0Ben Murdochnamespace v8 { 131b268ca467c924004286c97bac133db489cf43d0Ben Murdochnamespace internal { 141b268ca467c924004286c97bac133db489cf43d0Ben Murdoch 151b268ca467c924004286c97bac133db489cf43d0Ben Murdoch#define __ ACCESS_MASM(masm) 161b268ca467c924004286c97bac133db489cf43d0Ben Murdoch 171b268ca467c924004286c97bac133db489cf43d0Ben Murdochvoid EmitDebugBreakSlot(MacroAssembler* masm) { 181b268ca467c924004286c97bac133db489cf43d0Ben Murdoch Label check_size; 191b268ca467c924004286c97bac133db489cf43d0Ben Murdoch __ bind(&check_size); 201b268ca467c924004286c97bac133db489cf43d0Ben Murdoch // oill r3, 0 211b268ca467c924004286c97bac133db489cf43d0Ben Murdoch // oill r3, 0 221b268ca467c924004286c97bac133db489cf43d0Ben Murdoch __ nop(Assembler::DEBUG_BREAK_NOP); 231b268ca467c924004286c97bac133db489cf43d0Ben Murdoch __ nop(Assembler::DEBUG_BREAK_NOP); 241b268ca467c924004286c97bac133db489cf43d0Ben Murdoch 251b268ca467c924004286c97bac133db489cf43d0Ben Murdoch // lr r0, r0 64-bit only 261b268ca467c924004286c97bac133db489cf43d0Ben Murdoch // lr r0, r0 64-bit only 271b268ca467c924004286c97bac133db489cf43d0Ben Murdoch // lr r0, r0 64-bit only 281b268ca467c924004286c97bac133db489cf43d0Ben Murdoch for (int i = 8; i < Assembler::kDebugBreakSlotLength; i += 2) { 291b268ca467c924004286c97bac133db489cf43d0Ben Murdoch __ nop(); 301b268ca467c924004286c97bac133db489cf43d0Ben Murdoch } 311b268ca467c924004286c97bac133db489cf43d0Ben Murdoch DCHECK_EQ(Assembler::kDebugBreakSlotLength, 321b268ca467c924004286c97bac133db489cf43d0Ben Murdoch masm->SizeOfCodeGeneratedSince(&check_size)); 331b268ca467c924004286c97bac133db489cf43d0Ben Murdoch} 341b268ca467c924004286c97bac133db489cf43d0Ben Murdoch 351b268ca467c924004286c97bac133db489cf43d0Ben Murdochvoid DebugCodegen::GenerateSlot(MacroAssembler* masm, RelocInfo::Mode mode) { 361b268ca467c924004286c97bac133db489cf43d0Ben Murdoch // Generate enough nop's to make space for a call instruction. 371b268ca467c924004286c97bac133db489cf43d0Ben Murdoch masm->RecordDebugBreakSlot(mode); 381b268ca467c924004286c97bac133db489cf43d0Ben Murdoch EmitDebugBreakSlot(masm); 391b268ca467c924004286c97bac133db489cf43d0Ben Murdoch} 401b268ca467c924004286c97bac133db489cf43d0Ben Murdoch 411b268ca467c924004286c97bac133db489cf43d0Ben Murdochvoid DebugCodegen::ClearDebugBreakSlot(Isolate* isolate, Address pc) { 421b268ca467c924004286c97bac133db489cf43d0Ben Murdoch CodePatcher patcher(isolate, pc, Assembler::kDebugBreakSlotLength); 431b268ca467c924004286c97bac133db489cf43d0Ben Murdoch EmitDebugBreakSlot(patcher.masm()); 441b268ca467c924004286c97bac133db489cf43d0Ben Murdoch} 451b268ca467c924004286c97bac133db489cf43d0Ben Murdoch 461b268ca467c924004286c97bac133db489cf43d0Ben Murdochvoid DebugCodegen::PatchDebugBreakSlot(Isolate* isolate, Address pc, 471b268ca467c924004286c97bac133db489cf43d0Ben Murdoch Handle<Code> code) { 4821efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch DCHECK(code->is_debug_stub()); 491b268ca467c924004286c97bac133db489cf43d0Ben Murdoch CodePatcher patcher(isolate, pc, Assembler::kDebugBreakSlotLength); 501b268ca467c924004286c97bac133db489cf43d0Ben Murdoch // Patch the code changing the debug break slot code from 511b268ca467c924004286c97bac133db489cf43d0Ben Murdoch // 521b268ca467c924004286c97bac133db489cf43d0Ben Murdoch // oill r3, 0 531b268ca467c924004286c97bac133db489cf43d0Ben Murdoch // oill r3, 0 541b268ca467c924004286c97bac133db489cf43d0Ben Murdoch // oill r3, 0 64-bit only 551b268ca467c924004286c97bac133db489cf43d0Ben Murdoch // lr r0, r0 64-bit only 561b268ca467c924004286c97bac133db489cf43d0Ben Murdoch // 571b268ca467c924004286c97bac133db489cf43d0Ben Murdoch // to a call to the debug break code, using a FIXED_SEQUENCE. 581b268ca467c924004286c97bac133db489cf43d0Ben Murdoch // 591b268ca467c924004286c97bac133db489cf43d0Ben Murdoch // iilf r14, <address> 6-bytes 601b268ca467c924004286c97bac133db489cf43d0Ben Murdoch // basr r14, r14A 2-bytes 611b268ca467c924004286c97bac133db489cf43d0Ben Murdoch // 621b268ca467c924004286c97bac133db489cf43d0Ben Murdoch // The 64bit sequence has an extra iihf. 631b268ca467c924004286c97bac133db489cf43d0Ben Murdoch // 641b268ca467c924004286c97bac133db489cf43d0Ben Murdoch // iihf r14, <high 32-bits address> 6-bytes 651b268ca467c924004286c97bac133db489cf43d0Ben Murdoch // iilf r14, <lower 32-bits address> 6-bytes 661b268ca467c924004286c97bac133db489cf43d0Ben Murdoch // basr r14, r14 2-bytes 671b268ca467c924004286c97bac133db489cf43d0Ben Murdoch patcher.masm()->mov(v8::internal::r14, 681b268ca467c924004286c97bac133db489cf43d0Ben Murdoch Operand(reinterpret_cast<intptr_t>(code->entry()))); 691b268ca467c924004286c97bac133db489cf43d0Ben Murdoch patcher.masm()->basr(v8::internal::r14, v8::internal::r14); 701b268ca467c924004286c97bac133db489cf43d0Ben Murdoch} 711b268ca467c924004286c97bac133db489cf43d0Ben Murdoch 721b268ca467c924004286c97bac133db489cf43d0Ben Murdochbool DebugCodegen::DebugBreakSlotIsPatched(Address pc) { 731b268ca467c924004286c97bac133db489cf43d0Ben Murdoch Instr current_instr = Assembler::instr_at(pc); 741b268ca467c924004286c97bac133db489cf43d0Ben Murdoch return !Assembler::IsNop(current_instr, Assembler::DEBUG_BREAK_NOP); 751b268ca467c924004286c97bac133db489cf43d0Ben Murdoch} 761b268ca467c924004286c97bac133db489cf43d0Ben Murdoch 771b268ca467c924004286c97bac133db489cf43d0Ben Murdochvoid DebugCodegen::GenerateDebugBreakStub(MacroAssembler* masm, 781b268ca467c924004286c97bac133db489cf43d0Ben Murdoch DebugBreakCallHelperMode mode) { 791b268ca467c924004286c97bac133db489cf43d0Ben Murdoch __ RecordComment("Debug break"); 801b268ca467c924004286c97bac133db489cf43d0Ben Murdoch { 811b268ca467c924004286c97bac133db489cf43d0Ben Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 821b268ca467c924004286c97bac133db489cf43d0Ben Murdoch 831b268ca467c924004286c97bac133db489cf43d0Ben Murdoch // Load padding words on stack. 841b268ca467c924004286c97bac133db489cf43d0Ben Murdoch __ LoadSmiLiteral(ip, Smi::FromInt(LiveEdit::kFramePaddingValue)); 851b268ca467c924004286c97bac133db489cf43d0Ben Murdoch for (int i = 0; i < LiveEdit::kFramePaddingInitialSize; i++) { 861b268ca467c924004286c97bac133db489cf43d0Ben Murdoch __ push(ip); 871b268ca467c924004286c97bac133db489cf43d0Ben Murdoch } 881b268ca467c924004286c97bac133db489cf43d0Ben Murdoch __ LoadSmiLiteral(ip, Smi::FromInt(LiveEdit::kFramePaddingInitialSize)); 891b268ca467c924004286c97bac133db489cf43d0Ben Murdoch __ push(ip); 901b268ca467c924004286c97bac133db489cf43d0Ben Murdoch 911b268ca467c924004286c97bac133db489cf43d0Ben Murdoch // Push arguments for DebugBreak call. 921b268ca467c924004286c97bac133db489cf43d0Ben Murdoch if (mode == SAVE_RESULT_REGISTER) { 931b268ca467c924004286c97bac133db489cf43d0Ben Murdoch // Break on return. 941b268ca467c924004286c97bac133db489cf43d0Ben Murdoch __ push(r2); 951b268ca467c924004286c97bac133db489cf43d0Ben Murdoch } else { 961b268ca467c924004286c97bac133db489cf43d0Ben Murdoch // Non-return breaks. 971b268ca467c924004286c97bac133db489cf43d0Ben Murdoch __ Push(masm->isolate()->factory()->the_hole_value()); 981b268ca467c924004286c97bac133db489cf43d0Ben Murdoch } 991b268ca467c924004286c97bac133db489cf43d0Ben Murdoch __ mov(r2, Operand(1)); 1001b268ca467c924004286c97bac133db489cf43d0Ben Murdoch __ mov(r3, 1011b268ca467c924004286c97bac133db489cf43d0Ben Murdoch Operand(ExternalReference( 1021b268ca467c924004286c97bac133db489cf43d0Ben Murdoch Runtime::FunctionForId(Runtime::kDebugBreak), masm->isolate()))); 1031b268ca467c924004286c97bac133db489cf43d0Ben Murdoch 1041b268ca467c924004286c97bac133db489cf43d0Ben Murdoch CEntryStub ceb(masm->isolate(), 1); 1051b268ca467c924004286c97bac133db489cf43d0Ben Murdoch __ CallStub(&ceb); 1061b268ca467c924004286c97bac133db489cf43d0Ben Murdoch 1071b268ca467c924004286c97bac133db489cf43d0Ben Murdoch if (FLAG_debug_code) { 1081b268ca467c924004286c97bac133db489cf43d0Ben Murdoch for (int i = 0; i < kNumJSCallerSaved; i++) { 1091b268ca467c924004286c97bac133db489cf43d0Ben Murdoch Register reg = {JSCallerSavedCode(i)}; 1101b268ca467c924004286c97bac133db489cf43d0Ben Murdoch // Do not clobber r2 if mode is SAVE_RESULT_REGISTER. It will 1111b268ca467c924004286c97bac133db489cf43d0Ben Murdoch // contain return value of the function. 1121b268ca467c924004286c97bac133db489cf43d0Ben Murdoch if (!(reg.is(r2) && (mode == SAVE_RESULT_REGISTER))) { 1131b268ca467c924004286c97bac133db489cf43d0Ben Murdoch __ mov(reg, Operand(kDebugZapValue)); 1141b268ca467c924004286c97bac133db489cf43d0Ben Murdoch } 1151b268ca467c924004286c97bac133db489cf43d0Ben Murdoch } 1161b268ca467c924004286c97bac133db489cf43d0Ben Murdoch } 1171b268ca467c924004286c97bac133db489cf43d0Ben Murdoch 1181b268ca467c924004286c97bac133db489cf43d0Ben Murdoch // Don't bother removing padding bytes pushed on the stack 1191b268ca467c924004286c97bac133db489cf43d0Ben Murdoch // as the frame is going to be restored right away. 1201b268ca467c924004286c97bac133db489cf43d0Ben Murdoch 1211b268ca467c924004286c97bac133db489cf43d0Ben Murdoch // Leave the internal frame. 1221b268ca467c924004286c97bac133db489cf43d0Ben Murdoch } 1231b268ca467c924004286c97bac133db489cf43d0Ben Murdoch 1241b268ca467c924004286c97bac133db489cf43d0Ben Murdoch // Now that the break point has been handled, resume normal execution by 1251b268ca467c924004286c97bac133db489cf43d0Ben Murdoch // jumping to the target address intended by the caller and that was 1261b268ca467c924004286c97bac133db489cf43d0Ben Murdoch // overwritten by the address of DebugBreakXXX. 1271b268ca467c924004286c97bac133db489cf43d0Ben Murdoch ExternalReference after_break_target = 1281b268ca467c924004286c97bac133db489cf43d0Ben Murdoch ExternalReference::debug_after_break_target_address(masm->isolate()); 1291b268ca467c924004286c97bac133db489cf43d0Ben Murdoch __ mov(ip, Operand(after_break_target)); 1301b268ca467c924004286c97bac133db489cf43d0Ben Murdoch __ LoadP(ip, MemOperand(ip)); 1311b268ca467c924004286c97bac133db489cf43d0Ben Murdoch __ JumpToJSEntry(ip); 1321b268ca467c924004286c97bac133db489cf43d0Ben Murdoch} 1331b268ca467c924004286c97bac133db489cf43d0Ben Murdoch 1341b268ca467c924004286c97bac133db489cf43d0Ben Murdochvoid DebugCodegen::GenerateFrameDropperLiveEdit(MacroAssembler* masm) { 1351b268ca467c924004286c97bac133db489cf43d0Ben Murdoch // Load the function pointer off of our current stack frame. 1361b268ca467c924004286c97bac133db489cf43d0Ben Murdoch __ LoadP(r3, MemOperand(fp, FrameDropperFrameConstants::kFunctionOffset)); 1371b268ca467c924004286c97bac133db489cf43d0Ben Murdoch 1381b268ca467c924004286c97bac133db489cf43d0Ben Murdoch // Pop return address and frame 1391b268ca467c924004286c97bac133db489cf43d0Ben Murdoch __ LeaveFrame(StackFrame::INTERNAL); 1401b268ca467c924004286c97bac133db489cf43d0Ben Murdoch 1411b268ca467c924004286c97bac133db489cf43d0Ben Murdoch ParameterCount dummy(0); 1421b268ca467c924004286c97bac133db489cf43d0Ben Murdoch __ FloodFunctionIfStepping(r3, no_reg, dummy, dummy); 1431b268ca467c924004286c97bac133db489cf43d0Ben Murdoch 1441b268ca467c924004286c97bac133db489cf43d0Ben Murdoch // Load context from the function. 1451b268ca467c924004286c97bac133db489cf43d0Ben Murdoch __ LoadP(cp, FieldMemOperand(r3, JSFunction::kContextOffset)); 1461b268ca467c924004286c97bac133db489cf43d0Ben Murdoch 1471b268ca467c924004286c97bac133db489cf43d0Ben Murdoch // Clear new.target as a safety measure. 1481b268ca467c924004286c97bac133db489cf43d0Ben Murdoch __ LoadRoot(r5, Heap::kUndefinedValueRootIndex); 1491b268ca467c924004286c97bac133db489cf43d0Ben Murdoch 1501b268ca467c924004286c97bac133db489cf43d0Ben Murdoch // Get function code. 1511b268ca467c924004286c97bac133db489cf43d0Ben Murdoch __ LoadP(ip, FieldMemOperand(r3, JSFunction::kSharedFunctionInfoOffset)); 1521b268ca467c924004286c97bac133db489cf43d0Ben Murdoch __ LoadP(ip, FieldMemOperand(ip, SharedFunctionInfo::kCodeOffset)); 1531b268ca467c924004286c97bac133db489cf43d0Ben Murdoch __ AddP(ip, Operand(Code::kHeaderSize - kHeapObjectTag)); 1541b268ca467c924004286c97bac133db489cf43d0Ben Murdoch 1551b268ca467c924004286c97bac133db489cf43d0Ben Murdoch // Re-run JSFunction, r3 is function, cp is context. 1561b268ca467c924004286c97bac133db489cf43d0Ben Murdoch __ Jump(ip); 1571b268ca467c924004286c97bac133db489cf43d0Ben Murdoch} 1581b268ca467c924004286c97bac133db489cf43d0Ben Murdoch 1591b268ca467c924004286c97bac133db489cf43d0Ben Murdochconst bool LiveEdit::kFrameDropperSupported = true; 1601b268ca467c924004286c97bac133db489cf43d0Ben Murdoch 1611b268ca467c924004286c97bac133db489cf43d0Ben Murdoch#undef __ 1621b268ca467c924004286c97bac133db489cf43d0Ben Murdoch} // namespace internal 1631b268ca467c924004286c97bac133db489cf43d0Ben Murdoch} // namespace v8 1641b268ca467c924004286c97bac133db489cf43d0Ben Murdoch 1651b268ca467c924004286c97bac133db489cf43d0Ben Murdoch#endif // V8_TARGET_ARCH_S390 166