OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 29 matching lines...) Expand all Loading... |
40 #ifdef ENABLE_DEBUGGER_SUPPORT | 40 #ifdef ENABLE_DEBUGGER_SUPPORT |
41 | 41 |
42 bool Debug::IsDebugBreakAtReturn(v8::internal::RelocInfo* rinfo) { | 42 bool Debug::IsDebugBreakAtReturn(v8::internal::RelocInfo* rinfo) { |
43 ASSERT(RelocInfo::IsJSReturn(rinfo->rmode())); | 43 ASSERT(RelocInfo::IsJSReturn(rinfo->rmode())); |
44 return rinfo->IsPatchedReturnSequence(); | 44 return rinfo->IsPatchedReturnSequence(); |
45 } | 45 } |
46 | 46 |
47 #define __ ACCESS_MASM(masm) | 47 #define __ ACCESS_MASM(masm) |
48 | 48 |
49 static void Generate_DebugBreakCallHelper(MacroAssembler* masm, | 49 static void Generate_DebugBreakCallHelper(MacroAssembler* masm, |
50 RegList pointer_regs, | 50 RegList object_regs, |
| 51 RegList non_object_regs, |
51 bool convert_call_to_jmp) { | 52 bool convert_call_to_jmp) { |
52 // Save the content of all general purpose registers in memory. This copy in | |
53 // memory is later pushed onto the JS expression stack for the fake JS frame | |
54 // generated and also to the C frame generated on top of that. In the JS | |
55 // frame ONLY the registers containing pointers will be pushed on the | |
56 // expression stack. This causes the GC to update these pointers so that | |
57 // they will have the correct value when returning from the debugger. | |
58 __ SaveRegistersToMemory(kJSCallerSaved); | |
59 | |
60 // Enter an internal frame. | 53 // Enter an internal frame. |
61 __ EnterInternalFrame(); | 54 __ EnterInternalFrame(); |
62 | 55 |
63 // Store the registers containing object pointers on the expression stack to | 56 // Store the registers containing live values on the expression stack to |
64 // make sure that these are correctly updated during GC. | 57 // make sure that these are correctly updated during GC. Non object values |
65 __ PushRegistersFromMemory(pointer_regs); | 58 // are stored as as two smi causing it to be untouched by GC. |
| 59 ASSERT((object_regs & ~kJSCallerSaved) == 0); |
| 60 ASSERT((non_object_regs & ~kJSCallerSaved) == 0); |
| 61 ASSERT((object_regs & non_object_regs) == 0); |
| 62 for (int i = 0; i < kNumJSCallerSaved; i++) { |
| 63 int r = JSCallerSavedCode(i); |
| 64 Register reg = { r }; |
| 65 ASSERT(!reg.is(kScratchRegister)); |
| 66 if ((object_regs & (1 << r)) != 0) { |
| 67 __ push(reg); |
| 68 } |
| 69 // Store the 64-bit value as two smis. |
| 70 if ((non_object_regs & (1 << r)) != 0) { |
| 71 __ movq(kScratchRegister, reg); |
| 72 __ Integer32ToSmi(reg, reg); |
| 73 __ push(reg); |
| 74 __ sar(kScratchRegister, Immediate(32)); |
| 75 __ Integer32ToSmi(kScratchRegister, kScratchRegister); |
| 76 __ push(kScratchRegister); |
| 77 } |
| 78 } |
66 | 79 |
67 #ifdef DEBUG | 80 #ifdef DEBUG |
68 __ RecordComment("// Calling from debug break to runtime - come in - over"); | 81 __ RecordComment("// Calling from debug break to runtime - come in - over"); |
69 #endif | 82 #endif |
70 __ xor_(rax, rax); // No arguments (argc == 0). | 83 __ xor_(rax, rax); // No arguments (argc == 0). |
71 __ movq(rbx, ExternalReference::debug_break()); | 84 __ movq(rbx, ExternalReference::debug_break()); |
72 | 85 |
73 CEntryStub ceb(1, ExitFrame::MODE_DEBUG); | 86 CEntryStub ceb(1); |
74 __ CallStub(&ceb); | 87 __ CallStub(&ceb); |
75 | 88 |
76 // Restore the register values containing object pointers from the expression | 89 // Restore the register values from the expression stack. |
77 // stack in the reverse order as they where pushed. | 90 for (int i = kNumJSCallerSaved - 1; i >= 0; i--) { |
78 __ PopRegistersToMemory(pointer_regs); | 91 int r = JSCallerSavedCode(i); |
| 92 Register reg = { r }; |
| 93 if (FLAG_debug_code) { |
| 94 __ Set(reg, kDebugZapValue); |
| 95 } |
| 96 if ((object_regs & (1 << r)) != 0) { |
| 97 __ pop(reg); |
| 98 } |
| 99 // Reconstruct the 64-bit value from two smis. |
| 100 if ((non_object_regs & (1 << r)) != 0) { |
| 101 __ pop(kScratchRegister); |
| 102 __ SmiToInteger32(kScratchRegister, kScratchRegister); |
| 103 __ shl(kScratchRegister, Immediate(32)); |
| 104 __ pop(reg); |
| 105 __ SmiToInteger32(reg, reg); |
| 106 __ or_(reg, kScratchRegister); |
| 107 } |
| 108 } |
79 | 109 |
80 // Get rid of the internal frame. | 110 // Get rid of the internal frame. |
81 __ LeaveInternalFrame(); | 111 __ LeaveInternalFrame(); |
82 | 112 |
83 // If this call did not replace a call but patched other code then there will | 113 // If this call did not replace a call but patched other code then there will |
84 // be an unwanted return address left on the stack. Here we get rid of that. | 114 // be an unwanted return address left on the stack. Here we get rid of that. |
85 if (convert_call_to_jmp) { | 115 if (convert_call_to_jmp) { |
86 __ pop(rax); | 116 __ addq(rsp, Immediate(kPointerSize)); |
87 } | 117 } |
88 | 118 |
89 // Finally restore all registers. | |
90 __ RestoreRegistersFromMemory(kJSCallerSaved); | |
91 | |
92 // Now that the break point has been handled, resume normal execution by | 119 // Now that the break point has been handled, resume normal execution by |
93 // jumping to the target address intended by the caller and that was | 120 // jumping to the target address intended by the caller and that was |
94 // overwritten by the address of DebugBreakXXX. | 121 // overwritten by the address of DebugBreakXXX. |
95 ExternalReference after_break_target = | 122 ExternalReference after_break_target = |
96 ExternalReference(Debug_Address::AfterBreakTarget()); | 123 ExternalReference(Debug_Address::AfterBreakTarget()); |
97 __ movq(kScratchRegister, after_break_target); | 124 __ movq(kScratchRegister, after_break_target); |
98 __ jmp(Operand(kScratchRegister, 0)); | 125 __ jmp(Operand(kScratchRegister, 0)); |
99 } | 126 } |
100 | 127 |
101 | 128 |
102 void Debug::GenerateCallICDebugBreak(MacroAssembler* masm) { | 129 void Debug::GenerateCallICDebugBreak(MacroAssembler* masm) { |
103 // Register state for IC call call (from ic-x64.cc) | 130 // Register state for IC call call (from ic-x64.cc) |
104 // ----------- S t a t e ------------- | 131 // ----------- S t a t e ------------- |
105 // -- rcx: function name | 132 // -- rcx: function name |
106 // ----------------------------------- | 133 // ----------------------------------- |
107 Generate_DebugBreakCallHelper(masm, rcx.bit(), false); | 134 Generate_DebugBreakCallHelper(masm, rcx.bit(), 0, false); |
108 } | 135 } |
109 | 136 |
110 | 137 |
111 void Debug::GenerateConstructCallDebugBreak(MacroAssembler* masm) { | 138 void Debug::GenerateConstructCallDebugBreak(MacroAssembler* masm) { |
112 // Register state just before return from JS function (from codegen-x64.cc). | 139 // Register state just before return from JS function (from codegen-x64.cc). |
113 // rax is the actual number of arguments not encoded as a smi, see comment | 140 // rax is the actual number of arguments not encoded as a smi, see comment |
114 // above IC call. | 141 // above IC call. |
115 // ----------- S t a t e ------------- | 142 // ----------- S t a t e ------------- |
116 // -- rax: number of arguments | 143 // -- rax: number of arguments |
117 // ----------------------------------- | 144 // ----------------------------------- |
118 // The number of arguments in rax is not smi encoded. | 145 // The number of arguments in rax is not smi encoded. |
119 Generate_DebugBreakCallHelper(masm, 0, false); | 146 Generate_DebugBreakCallHelper(masm, rdi.bit(), rax.bit(), false); |
120 } | 147 } |
121 | 148 |
122 | 149 |
123 void Debug::GenerateKeyedLoadICDebugBreak(MacroAssembler* masm) { | 150 void Debug::GenerateKeyedLoadICDebugBreak(MacroAssembler* masm) { |
124 // Register state for keyed IC load call (from ic-x64.cc). | 151 // Register state for keyed IC load call (from ic-x64.cc). |
125 // ----------- S t a t e ------------- | 152 // ----------- S t a t e ------------- |
126 // -- rax : key | 153 // -- rax : key |
127 // -- rdx : receiver | 154 // -- rdx : receiver |
128 // ----------------------------------- | 155 // ----------------------------------- |
129 Generate_DebugBreakCallHelper(masm, rax.bit() | rdx.bit(), false); | 156 Generate_DebugBreakCallHelper(masm, rax.bit() | rdx.bit(), 0, false); |
130 } | 157 } |
131 | 158 |
132 | 159 |
133 void Debug::GenerateKeyedStoreICDebugBreak(MacroAssembler* masm) { | 160 void Debug::GenerateKeyedStoreICDebugBreak(MacroAssembler* masm) { |
134 // Register state for keyed IC load call (from ic-x64.cc). | 161 // Register state for keyed IC load call (from ic-x64.cc). |
135 // ----------- S t a t e ------------- | 162 // ----------- S t a t e ------------- |
136 // -- rax : value | 163 // -- rax : value |
137 // -- rcx : key | 164 // -- rcx : key |
138 // -- rdx : receiver | 165 // -- rdx : receiver |
139 // ----------------------------------- | 166 // ----------------------------------- |
140 Generate_DebugBreakCallHelper(masm, rax.bit() | rcx.bit() | rdx.bit(), false); | 167 Generate_DebugBreakCallHelper( |
| 168 masm, rax.bit() | rcx.bit() | rdx.bit(), 0, false); |
141 } | 169 } |
142 | 170 |
143 | 171 |
144 void Debug::GenerateLoadICDebugBreak(MacroAssembler* masm) { | 172 void Debug::GenerateLoadICDebugBreak(MacroAssembler* masm) { |
145 // Register state for IC load call (from ic-x64.cc). | 173 // Register state for IC load call (from ic-x64.cc). |
146 // ----------- S t a t e ------------- | 174 // ----------- S t a t e ------------- |
147 // -- rax : receiver | 175 // -- rax : receiver |
148 // -- rcx : name | 176 // -- rcx : name |
149 // ----------------------------------- | 177 // ----------------------------------- |
150 Generate_DebugBreakCallHelper(masm, rax.bit() | rcx.bit(), false); | 178 Generate_DebugBreakCallHelper(masm, rax.bit() | rcx.bit(), 0, false); |
151 } | 179 } |
152 | 180 |
153 | 181 |
154 void Debug::GenerateReturnDebugBreak(MacroAssembler* masm) { | 182 void Debug::GenerateReturnDebugBreak(MacroAssembler* masm) { |
155 // Register state just before return from JS function (from codegen-x64.cc). | 183 // Register state just before return from JS function (from codegen-x64.cc). |
156 // ----------- S t a t e ------------- | 184 // ----------- S t a t e ------------- |
157 // -- rax: return value | 185 // -- rax: return value |
158 // ----------------------------------- | 186 // ----------------------------------- |
159 Generate_DebugBreakCallHelper(masm, rax.bit(), true); | 187 Generate_DebugBreakCallHelper(masm, rax.bit(), 0, true); |
160 } | 188 } |
161 | 189 |
162 | 190 |
163 void Debug::GenerateStoreICDebugBreak(MacroAssembler* masm) { | 191 void Debug::GenerateStoreICDebugBreak(MacroAssembler* masm) { |
164 // Register state for IC store call (from ic-x64.cc). | 192 // Register state for IC store call (from ic-x64.cc). |
165 // ----------- S t a t e ------------- | 193 // ----------- S t a t e ------------- |
166 // -- rax : value | 194 // -- rax : value |
167 // -- rcx : name | 195 // -- rcx : name |
168 // -- rdx : receiver | 196 // -- rdx : receiver |
169 // ----------------------------------- | 197 // ----------------------------------- |
170 Generate_DebugBreakCallHelper(masm, rax.bit() | rcx.bit() | rdx.bit(), false); | 198 Generate_DebugBreakCallHelper( |
| 199 masm, rax.bit() | rcx.bit() | rdx.bit(), 0, false); |
171 } | 200 } |
172 | 201 |
173 | 202 |
174 void Debug::GenerateStubNoRegistersDebugBreak(MacroAssembler* masm) { | 203 void Debug::GenerateStubNoRegistersDebugBreak(MacroAssembler* masm) { |
175 // Register state for stub CallFunction (from CallFunctionStub in ic-x64.cc). | 204 // Register state for stub CallFunction (from CallFunctionStub in ic-x64.cc). |
176 // ----------- S t a t e ------------- | 205 // ----------- S t a t e ------------- |
177 // No registers used on entry. | 206 // No registers used on entry. |
178 // ----------------------------------- | 207 // ----------------------------------- |
179 Generate_DebugBreakCallHelper(masm, 0, false); | 208 Generate_DebugBreakCallHelper(masm, 0, 0, false); |
180 } | 209 } |
181 | 210 |
182 | 211 |
183 void Debug::GenerateSlot(MacroAssembler* masm) { | 212 void Debug::GenerateSlot(MacroAssembler* masm) { |
184 // Generate enough nop's to make space for a call instruction. | 213 // Generate enough nop's to make space for a call instruction. |
185 Label check_codesize; | 214 Label check_codesize; |
186 __ bind(&check_codesize); | 215 __ bind(&check_codesize); |
187 __ RecordDebugBreakSlot(); | 216 __ RecordDebugBreakSlot(); |
188 for (int i = 0; i < Assembler::kDebugBreakSlotLength; i++) { | 217 for (int i = 0; i < Assembler::kDebugBreakSlotLength; i++) { |
189 __ nop(); | 218 __ nop(); |
190 } | 219 } |
191 ASSERT_EQ(Assembler::kDebugBreakSlotLength, | 220 ASSERT_EQ(Assembler::kDebugBreakSlotLength, |
192 masm->SizeOfCodeGeneratedSince(&check_codesize)); | 221 masm->SizeOfCodeGeneratedSince(&check_codesize)); |
193 } | 222 } |
194 | 223 |
195 | 224 |
196 void Debug::GenerateSlotDebugBreak(MacroAssembler* masm) { | 225 void Debug::GenerateSlotDebugBreak(MacroAssembler* masm) { |
197 // In the places where a debug break slot is inserted no registers can contain | 226 // In the places where a debug break slot is inserted no registers can contain |
198 // object pointers. | 227 // object pointers. |
199 Generate_DebugBreakCallHelper(masm, 0, true); | 228 Generate_DebugBreakCallHelper(masm, 0, 0, true); |
200 } | 229 } |
201 | 230 |
202 | 231 |
203 void Debug::GeneratePlainReturnLiveEdit(MacroAssembler* masm) { | 232 void Debug::GeneratePlainReturnLiveEdit(MacroAssembler* masm) { |
204 masm->ret(0); | 233 masm->ret(0); |
205 } | 234 } |
206 | 235 |
207 | 236 |
208 void Debug::GenerateFrameDropperLiveEdit(MacroAssembler* masm) { | 237 void Debug::GenerateFrameDropperLiveEdit(MacroAssembler* masm) { |
209 ExternalReference restarter_frame_function_slot = | 238 ExternalReference restarter_frame_function_slot = |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
274 ASSERT(IsDebugBreakSlot()); | 303 ASSERT(IsDebugBreakSlot()); |
275 rinfo()->PatchCode(original_rinfo()->pc(), Assembler::kDebugBreakSlotLength); | 304 rinfo()->PatchCode(original_rinfo()->pc(), Assembler::kDebugBreakSlotLength); |
276 } | 305 } |
277 | 306 |
278 | 307 |
279 #endif // ENABLE_DEBUGGER_SUPPORT | 308 #endif // ENABLE_DEBUGGER_SUPPORT |
280 | 309 |
281 } } // namespace v8::internal | 310 } } // namespace v8::internal |
282 | 311 |
283 #endif // V8_TARGET_ARCH_X64 | 312 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |