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/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