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