• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
EmitDebugBreakSlot(MacroAssembler * masm)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 
GenerateSlot(MacroAssembler * masm,RelocInfo::Mode mode)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 
ClearDebugBreakSlot(Isolate * isolate,Address pc)35 void DebugCodegen::ClearDebugBreakSlot(Isolate* isolate, Address pc) {
36   CodePatcher patcher(isolate, pc, Assembler::kDebugBreakSlotLength);
37   EmitDebugBreakSlot(patcher.masm());
38 }
39 
40 
PatchDebugBreakSlot(Isolate * isolate,Address pc,Handle<Code> code)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 
DebugBreakSlotIsPatched(Address pc)55 bool DebugCodegen::DebugBreakSlotIsPatched(Address pc) {
56   return !Assembler::IsNop(pc);
57 }
58 
GenerateDebugBreakStub(MacroAssembler * masm,DebugBreakCallHelperMode mode)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 
GenerateHandleDebuggerStatement(MacroAssembler * masm)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 
GenerateFrameDropperTrampoline(MacroAssembler * masm)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