Home | History | Annotate | Download | only in s390
      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