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