debug-ia32.cc revision 62ed631aa0ff23db68a47fd423efa9c019ff2c9e
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
13namespace v8 {
14namespace internal {
15
16#define __ ACCESS_MASM(masm)
17
18
19void 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
28void 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
35void DebugCodegen::ClearDebugBreakSlot(Isolate* isolate, Address pc) {
36  CodePatcher patcher(isolate, pc, Assembler::kDebugBreakSlotLength);
37  EmitDebugBreakSlot(patcher.masm());
38}
39
40
41void 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
55bool DebugCodegen::DebugBreakSlotIsPatched(Address pc) {
56  return !Assembler::IsNop(pc);
57}
58
59void 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
102void 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
113void 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
133const bool LiveEdit::kFrameDropperSupported = true;
134
135#undef __
136
137}  // namespace internal
138}  // namespace v8
139
140#endif  // V8_TARGET_ARCH_IA32
141