Home | History | Annotate | Download | only in x64
      1 // Copyright 2012 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_X64
      6 
      7 #include "src/debug/debug.h"
      8 
      9 #include "src/assembler.h"
     10 #include "src/codegen.h"
     11 #include "src/debug/liveedit.h"
     12 #include "src/objects-inl.h"
     13 
     14 namespace v8 {
     15 namespace internal {
     16 
     17 #define __ ACCESS_MASM(masm)
     18 
     19 
     20 void EmitDebugBreakSlot(MacroAssembler* masm) {
     21   Label check_codesize;
     22   __ bind(&check_codesize);
     23   __ Nop(Assembler::kDebugBreakSlotLength);
     24   DCHECK_EQ(Assembler::kDebugBreakSlotLength,
     25             masm->SizeOfCodeGeneratedSince(&check_codesize));
     26 }
     27 
     28 
     29 void DebugCodegen::GenerateSlot(MacroAssembler* masm, RelocInfo::Mode mode) {
     30   // Generate enough nop's to make space for a call instruction.
     31   masm->RecordDebugBreakSlot(mode);
     32   EmitDebugBreakSlot(masm);
     33 }
     34 
     35 
     36 void DebugCodegen::ClearDebugBreakSlot(Isolate* isolate, Address pc) {
     37   CodePatcher patcher(isolate, pc, Assembler::kDebugBreakSlotLength);
     38   EmitDebugBreakSlot(patcher.masm());
     39 }
     40 
     41 
     42 void DebugCodegen::PatchDebugBreakSlot(Isolate* isolate, Address pc,
     43                                        Handle<Code> code) {
     44   DCHECK(code->is_debug_stub());
     45   static const int kSize = Assembler::kDebugBreakSlotLength;
     46   CodePatcher patcher(isolate, pc, kSize);
     47   Label check_codesize;
     48   patcher.masm()->bind(&check_codesize);
     49   patcher.masm()->movp(kScratchRegister, reinterpret_cast<void*>(code->entry()),
     50                        Assembler::RelocInfoNone());
     51   patcher.masm()->call(kScratchRegister);
     52   // Check that the size of the code generated is as expected.
     53   DCHECK_EQ(kSize, patcher.masm()->SizeOfCodeGeneratedSince(&check_codesize));
     54 }
     55 
     56 bool DebugCodegen::DebugBreakSlotIsPatched(Address pc) {
     57   return !Assembler::IsNop(pc);
     58 }
     59 
     60 void DebugCodegen::GenerateDebugBreakStub(MacroAssembler* masm,
     61                                           DebugBreakCallHelperMode mode) {
     62   __ RecordComment("Debug break");
     63 
     64   // Enter an internal frame.
     65   {
     66     FrameScope scope(masm, StackFrame::INTERNAL);
     67 
     68     // Push arguments for DebugBreak call.
     69     if (mode == SAVE_RESULT_REGISTER) {
     70       // Break on return.
     71       __ Push(rax);
     72     } else {
     73       // Non-return breaks.
     74       __ Push(masm->isolate()->factory()->the_hole_value());
     75     }
     76 
     77     __ CallRuntime(Runtime::kDebugBreak, 1, kDontSaveFPRegs);
     78 
     79     if (FLAG_debug_code) {
     80       for (int i = 0; i < kNumJSCallerSaved; ++i) {
     81         Register reg = {JSCallerSavedCode(i)};
     82         // Do not clobber rax if mode is SAVE_RESULT_REGISTER. It will
     83         // contain return value of the function.
     84         if (!(reg.is(rax) && (mode == SAVE_RESULT_REGISTER))) {
     85           __ Set(reg, kDebugZapValue);
     86         }
     87       }
     88     }
     89     // Get rid of the internal frame.
     90   }
     91 
     92   __ MaybeDropFrames();
     93 
     94   // Return to caller.
     95   __ ret(0);
     96 }
     97 
     98 void DebugCodegen::GenerateHandleDebuggerStatement(MacroAssembler* masm) {
     99   {
    100     FrameScope scope(masm, StackFrame::INTERNAL);
    101     __ CallRuntime(Runtime::kHandleDebuggerStatement, 0);
    102   }
    103   __ MaybeDropFrames();
    104 
    105   // Return to caller.
    106   __ ret(0);
    107 }
    108 
    109 void DebugCodegen::GenerateFrameDropperTrampoline(MacroAssembler* masm) {
    110   // Frame is being dropped:
    111   // - Drop to the target frame specified by rbx.
    112   // - Look up current function on the frame.
    113   // - Leave the frame.
    114   // - Restart the frame by calling the function.
    115   __ movp(rbp, rbx);
    116   __ movp(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
    117   __ leave();
    118 
    119   __ movp(rbx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
    120   __ LoadSharedFunctionInfoSpecialField(
    121       rbx, rbx, SharedFunctionInfo::kFormalParameterCountOffset);
    122 
    123   ParameterCount dummy(rbx);
    124   __ InvokeFunction(rdi, no_reg, dummy, dummy, JUMP_FUNCTION,
    125                     CheckDebugStepCallWrapper());
    126 }
    127 
    128 const bool LiveEdit::kFrameDropperSupported = true;
    129 
    130 #undef __
    131 
    132 }  // namespace internal
    133 }  // namespace v8
    134 
    135 #endif  // V8_TARGET_ARCH_X64
    136