| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "v8.h" | 5 #include "v8.h" |
| 6 | 6 |
| 7 #if V8_TARGET_ARCH_X64 | 7 #if V8_TARGET_ARCH_X64 |
| 8 | 8 |
| 9 #include "assembler.h" | 9 #include "assembler.h" |
| 10 #include "codegen.h" | 10 #include "codegen.h" |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 58 debug_info_->GetIsolate()->builtins()->Slot_DebugBreak()->entry(), | 58 debug_info_->GetIsolate()->builtins()->Slot_DebugBreak()->entry(), |
| 59 Assembler::kDebugBreakSlotLength - Assembler::kCallSequenceLength); | 59 Assembler::kDebugBreakSlotLength - Assembler::kCallSequenceLength); |
| 60 } | 60 } |
| 61 | 61 |
| 62 | 62 |
| 63 void BreakLocationIterator::ClearDebugBreakAtSlot() { | 63 void BreakLocationIterator::ClearDebugBreakAtSlot() { |
| 64 ASSERT(IsDebugBreakSlot()); | 64 ASSERT(IsDebugBreakSlot()); |
| 65 rinfo()->PatchCode(original_rinfo()->pc(), Assembler::kDebugBreakSlotLength); | 65 rinfo()->PatchCode(original_rinfo()->pc(), Assembler::kDebugBreakSlotLength); |
| 66 } | 66 } |
| 67 | 67 |
| 68 const bool Debug::FramePaddingLayout::kIsSupported = true; | |
| 69 | |
| 70 | 68 |
| 71 #define __ ACCESS_MASM(masm) | 69 #define __ ACCESS_MASM(masm) |
| 72 | 70 |
| 73 | 71 |
| 74 static void Generate_DebugBreakCallHelper(MacroAssembler* masm, | 72 static void Generate_DebugBreakCallHelper(MacroAssembler* masm, |
| 75 RegList object_regs, | 73 RegList object_regs, |
| 76 RegList non_object_regs, | 74 RegList non_object_regs, |
| 77 bool convert_call_to_jmp) { | 75 bool convert_call_to_jmp) { |
| 78 // Enter an internal frame. | 76 // Enter an internal frame. |
| 79 { | 77 { |
| 80 FrameScope scope(masm, StackFrame::INTERNAL); | 78 FrameScope scope(masm, StackFrame::INTERNAL); |
| 81 | 79 |
| 82 // Load padding words on stack. | 80 // Load padding words on stack. |
| 83 for (int i = 0; i < Debug::FramePaddingLayout::kInitialSize; i++) { | 81 for (int i = 0; i < LiveEdit::kFramePaddingInitialSize; i++) { |
| 84 __ Push(Smi::FromInt(Debug::FramePaddingLayout::kPaddingValue)); | 82 __ Push(Smi::FromInt(LiveEdit::kFramePaddingValue)); |
| 85 } | 83 } |
| 86 __ Push(Smi::FromInt(Debug::FramePaddingLayout::kInitialSize)); | 84 __ Push(Smi::FromInt(LiveEdit::kFramePaddingInitialSize)); |
| 87 | 85 |
| 88 // Store the registers containing live values on the expression stack to | 86 // Store the registers containing live values on the expression stack to |
| 89 // make sure that these are correctly updated during GC. Non object values | 87 // make sure that these are correctly updated during GC. Non object values |
| 90 // are stored as as two smis causing it to be untouched by GC. | 88 // are stored as as two smis causing it to be untouched by GC. |
| 91 ASSERT((object_regs & ~kJSCallerSaved) == 0); | 89 ASSERT((object_regs & ~kJSCallerSaved) == 0); |
| 92 ASSERT((non_object_regs & ~kJSCallerSaved) == 0); | 90 ASSERT((non_object_regs & ~kJSCallerSaved) == 0); |
| 93 ASSERT((object_regs & non_object_regs) == 0); | 91 ASSERT((object_regs & non_object_regs) == 0); |
| 94 for (int i = 0; i < kNumJSCallerSaved; i++) { | 92 for (int i = 0; i < kNumJSCallerSaved; i++) { |
| 95 int r = JSCallerSavedCode(i); | 93 int r = JSCallerSavedCode(i); |
| 96 Register reg = { r }; | 94 Register reg = { r }; |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 145 // Now that the break point has been handled, resume normal execution by | 143 // Now that the break point has been handled, resume normal execution by |
| 146 // jumping to the target address intended by the caller and that was | 144 // jumping to the target address intended by the caller and that was |
| 147 // overwritten by the address of DebugBreakXXX. | 145 // overwritten by the address of DebugBreakXXX. |
| 148 ExternalReference after_break_target = | 146 ExternalReference after_break_target = |
| 149 ExternalReference::debug_after_break_target_address(masm->isolate()); | 147 ExternalReference::debug_after_break_target_address(masm->isolate()); |
| 150 __ Move(kScratchRegister, after_break_target); | 148 __ Move(kScratchRegister, after_break_target); |
| 151 __ Jump(Operand(kScratchRegister, 0)); | 149 __ Jump(Operand(kScratchRegister, 0)); |
| 152 } | 150 } |
| 153 | 151 |
| 154 | 152 |
| 155 void Debug::GenerateCallICStubDebugBreak(MacroAssembler* masm) { | 153 void DebugCodegen::GenerateCallICStubDebugBreak(MacroAssembler* masm) { |
| 156 // Register state for CallICStub | 154 // Register state for CallICStub |
| 157 // ----------- S t a t e ------------- | 155 // ----------- S t a t e ------------- |
| 158 // -- rdx : type feedback slot (smi) | 156 // -- rdx : type feedback slot (smi) |
| 159 // -- rdi : function | 157 // -- rdi : function |
| 160 // ----------------------------------- | 158 // ----------------------------------- |
| 161 Generate_DebugBreakCallHelper(masm, rdx.bit() | rdi.bit(), 0, false); | 159 Generate_DebugBreakCallHelper(masm, rdx.bit() | rdi.bit(), 0, false); |
| 162 } | 160 } |
| 163 | 161 |
| 164 | 162 |
| 165 void Debug::GenerateLoadICDebugBreak(MacroAssembler* masm) { | 163 void DebugCodegen::GenerateLoadICDebugBreak(MacroAssembler* masm) { |
| 166 // Register state for IC load call (from ic-x64.cc). | 164 // Register state for IC load call (from ic-x64.cc). |
| 167 // ----------- S t a t e ------------- | 165 // ----------- S t a t e ------------- |
| 168 // -- rax : receiver | 166 // -- rax : receiver |
| 169 // -- rcx : name | 167 // -- rcx : name |
| 170 // ----------------------------------- | 168 // ----------------------------------- |
| 171 Generate_DebugBreakCallHelper(masm, rax.bit() | rcx.bit(), 0, false); | 169 Generate_DebugBreakCallHelper(masm, rax.bit() | rcx.bit(), 0, false); |
| 172 } | 170 } |
| 173 | 171 |
| 174 | 172 |
| 175 void Debug::GenerateStoreICDebugBreak(MacroAssembler* masm) { | 173 void DebugCodegen::GenerateStoreICDebugBreak(MacroAssembler* masm) { |
| 176 // Register state for IC store call (from ic-x64.cc). | 174 // Register state for IC store call (from ic-x64.cc). |
| 177 // ----------- S t a t e ------------- | 175 // ----------- S t a t e ------------- |
| 178 // -- rax : value | 176 // -- rax : value |
| 179 // -- rcx : name | 177 // -- rcx : name |
| 180 // -- rdx : receiver | 178 // -- rdx : receiver |
| 181 // ----------------------------------- | 179 // ----------------------------------- |
| 182 Generate_DebugBreakCallHelper( | 180 Generate_DebugBreakCallHelper( |
| 183 masm, rax.bit() | rcx.bit() | rdx.bit(), 0, false); | 181 masm, rax.bit() | rcx.bit() | rdx.bit(), 0, false); |
| 184 } | 182 } |
| 185 | 183 |
| 186 | 184 |
| 187 void Debug::GenerateKeyedLoadICDebugBreak(MacroAssembler* masm) { | 185 void DebugCodegen::GenerateKeyedLoadICDebugBreak(MacroAssembler* masm) { |
| 188 // Register state for keyed IC load call (from ic-x64.cc). | 186 // Register state for keyed IC load call (from ic-x64.cc). |
| 189 // ----------- S t a t e ------------- | 187 // ----------- S t a t e ------------- |
| 190 // -- rax : key | 188 // -- rax : key |
| 191 // -- rdx : receiver | 189 // -- rdx : receiver |
| 192 // ----------------------------------- | 190 // ----------------------------------- |
| 193 Generate_DebugBreakCallHelper(masm, rax.bit() | rdx.bit(), 0, false); | 191 Generate_DebugBreakCallHelper(masm, rax.bit() | rdx.bit(), 0, false); |
| 194 } | 192 } |
| 195 | 193 |
| 196 | 194 |
| 197 void Debug::GenerateKeyedStoreICDebugBreak(MacroAssembler* masm) { | 195 void DebugCodegen::GenerateKeyedStoreICDebugBreak(MacroAssembler* masm) { |
| 198 // Register state for keyed IC load call (from ic-x64.cc). | 196 // Register state for keyed IC load call (from ic-x64.cc). |
| 199 // ----------- S t a t e ------------- | 197 // ----------- S t a t e ------------- |
| 200 // -- rax : value | 198 // -- rax : value |
| 201 // -- rcx : key | 199 // -- rcx : key |
| 202 // -- rdx : receiver | 200 // -- rdx : receiver |
| 203 // ----------------------------------- | 201 // ----------------------------------- |
| 204 Generate_DebugBreakCallHelper( | 202 Generate_DebugBreakCallHelper( |
| 205 masm, rax.bit() | rcx.bit() | rdx.bit(), 0, false); | 203 masm, rax.bit() | rcx.bit() | rdx.bit(), 0, false); |
| 206 } | 204 } |
| 207 | 205 |
| 208 | 206 |
| 209 void Debug::GenerateCompareNilICDebugBreak(MacroAssembler* masm) { | 207 void DebugCodegen::GenerateCompareNilICDebugBreak(MacroAssembler* masm) { |
| 210 // Register state for CompareNil IC | 208 // Register state for CompareNil IC |
| 211 // ----------- S t a t e ------------- | 209 // ----------- S t a t e ------------- |
| 212 // -- rax : value | 210 // -- rax : value |
| 213 // ----------------------------------- | 211 // ----------------------------------- |
| 214 Generate_DebugBreakCallHelper(masm, rax.bit(), 0, false); | 212 Generate_DebugBreakCallHelper(masm, rax.bit(), 0, false); |
| 215 } | 213 } |
| 216 | 214 |
| 217 | 215 |
| 218 void Debug::GenerateReturnDebugBreak(MacroAssembler* masm) { | 216 void DebugCodegen::GenerateReturnDebugBreak(MacroAssembler* masm) { |
| 219 // Register state just before return from JS function (from codegen-x64.cc). | 217 // Register state just before return from JS function (from codegen-x64.cc). |
| 220 // ----------- S t a t e ------------- | 218 // ----------- S t a t e ------------- |
| 221 // -- rax: return value | 219 // -- rax: return value |
| 222 // ----------------------------------- | 220 // ----------------------------------- |
| 223 Generate_DebugBreakCallHelper(masm, rax.bit(), 0, true); | 221 Generate_DebugBreakCallHelper(masm, rax.bit(), 0, true); |
| 224 } | 222 } |
| 225 | 223 |
| 226 | 224 |
| 227 void Debug::GenerateCallFunctionStubDebugBreak(MacroAssembler* masm) { | 225 void DebugCodegen::GenerateCallFunctionStubDebugBreak(MacroAssembler* masm) { |
| 228 // Register state for CallFunctionStub (from code-stubs-x64.cc). | 226 // Register state for CallFunctionStub (from code-stubs-x64.cc). |
| 229 // ----------- S t a t e ------------- | 227 // ----------- S t a t e ------------- |
| 230 // -- rdi : function | 228 // -- rdi : function |
| 231 // ----------------------------------- | 229 // ----------------------------------- |
| 232 Generate_DebugBreakCallHelper(masm, rdi.bit(), 0, false); | 230 Generate_DebugBreakCallHelper(masm, rdi.bit(), 0, false); |
| 233 } | 231 } |
| 234 | 232 |
| 235 | 233 |
| 236 void Debug::GenerateCallConstructStubDebugBreak(MacroAssembler* masm) { | 234 void DebugCodegen::GenerateCallConstructStubDebugBreak(MacroAssembler* masm) { |
| 237 // Register state for CallConstructStub (from code-stubs-x64.cc). | 235 // Register state for CallConstructStub (from code-stubs-x64.cc). |
| 238 // rax is the actual number of arguments not encoded as a smi, see comment | 236 // rax is the actual number of arguments not encoded as a smi, see comment |
| 239 // above IC call. | 237 // above IC call. |
| 240 // ----------- S t a t e ------------- | 238 // ----------- S t a t e ------------- |
| 241 // -- rax: number of arguments | 239 // -- rax: number of arguments |
| 242 // ----------------------------------- | 240 // ----------------------------------- |
| 243 // The number of arguments in rax is not smi encoded. | 241 // The number of arguments in rax is not smi encoded. |
| 244 Generate_DebugBreakCallHelper(masm, rdi.bit(), rax.bit(), false); | 242 Generate_DebugBreakCallHelper(masm, rdi.bit(), rax.bit(), false); |
| 245 } | 243 } |
| 246 | 244 |
| 247 | 245 |
| 248 void Debug::GenerateCallConstructStubRecordDebugBreak(MacroAssembler* masm) { | 246 void DebugCodegen::GenerateCallConstructStubRecordDebugBreak( |
| 247 MacroAssembler* masm) { |
| 249 // Register state for CallConstructStub (from code-stubs-x64.cc). | 248 // Register state for CallConstructStub (from code-stubs-x64.cc). |
| 250 // rax is the actual number of arguments not encoded as a smi, see comment | 249 // rax is the actual number of arguments not encoded as a smi, see comment |
| 251 // above IC call. | 250 // above IC call. |
| 252 // ----------- S t a t e ------------- | 251 // ----------- S t a t e ------------- |
| 253 // -- rax: number of arguments | 252 // -- rax: number of arguments |
| 254 // -- rbx: feedback array | 253 // -- rbx: feedback array |
| 255 // -- rdx: feedback slot (smi) | 254 // -- rdx: feedback slot (smi) |
| 256 // ----------------------------------- | 255 // ----------------------------------- |
| 257 // The number of arguments in rax is not smi encoded. | 256 // The number of arguments in rax is not smi encoded. |
| 258 Generate_DebugBreakCallHelper(masm, rbx.bit() | rdx.bit() | rdi.bit(), | 257 Generate_DebugBreakCallHelper(masm, rbx.bit() | rdx.bit() | rdi.bit(), |
| 259 rax.bit(), false); | 258 rax.bit(), false); |
| 260 } | 259 } |
| 261 | 260 |
| 262 | 261 |
| 263 void Debug::GenerateSlot(MacroAssembler* masm) { | 262 void DebugCodegen::GenerateSlot(MacroAssembler* masm) { |
| 264 // Generate enough nop's to make space for a call instruction. | 263 // Generate enough nop's to make space for a call instruction. |
| 265 Label check_codesize; | 264 Label check_codesize; |
| 266 __ bind(&check_codesize); | 265 __ bind(&check_codesize); |
| 267 __ RecordDebugBreakSlot(); | 266 __ RecordDebugBreakSlot(); |
| 268 __ Nop(Assembler::kDebugBreakSlotLength); | 267 __ Nop(Assembler::kDebugBreakSlotLength); |
| 269 ASSERT_EQ(Assembler::kDebugBreakSlotLength, | 268 ASSERT_EQ(Assembler::kDebugBreakSlotLength, |
| 270 masm->SizeOfCodeGeneratedSince(&check_codesize)); | 269 masm->SizeOfCodeGeneratedSince(&check_codesize)); |
| 271 } | 270 } |
| 272 | 271 |
| 273 | 272 |
| 274 void Debug::GenerateSlotDebugBreak(MacroAssembler* masm) { | 273 void DebugCodegen::GenerateSlotDebugBreak(MacroAssembler* masm) { |
| 275 // In the places where a debug break slot is inserted no registers can contain | 274 // In the places where a debug break slot is inserted no registers can contain |
| 276 // object pointers. | 275 // object pointers. |
| 277 Generate_DebugBreakCallHelper(masm, 0, 0, true); | 276 Generate_DebugBreakCallHelper(masm, 0, 0, true); |
| 278 } | 277 } |
| 279 | 278 |
| 280 | 279 |
| 281 void Debug::GeneratePlainReturnLiveEdit(MacroAssembler* masm) { | 280 void DebugCodegen::GeneratePlainReturnLiveEdit(MacroAssembler* masm) { |
| 282 masm->ret(0); | 281 masm->ret(0); |
| 283 } | 282 } |
| 284 | 283 |
| 285 | 284 |
| 286 void Debug::GenerateFrameDropperLiveEdit(MacroAssembler* masm) { | 285 void DebugCodegen::GenerateFrameDropperLiveEdit(MacroAssembler* masm) { |
| 287 ExternalReference restarter_frame_function_slot = | 286 ExternalReference restarter_frame_function_slot = |
| 288 ExternalReference::debug_restarter_frame_function_pointer_address( | 287 ExternalReference::debug_restarter_frame_function_pointer_address( |
| 289 masm->isolate()); | 288 masm->isolate()); |
| 290 __ Move(rax, restarter_frame_function_slot); | 289 __ Move(rax, restarter_frame_function_slot); |
| 291 __ movp(Operand(rax, 0), Immediate(0)); | 290 __ movp(Operand(rax, 0), Immediate(0)); |
| 292 | 291 |
| 293 // We do not know our frame height, but set rsp based on rbp. | 292 // We do not know our frame height, but set rsp based on rbp. |
| 294 __ leap(rsp, Operand(rbp, -1 * kPointerSize)); | 293 __ leap(rsp, Operand(rbp, -1 * kPointerSize)); |
| 295 | 294 |
| 296 __ Pop(rdi); // Function. | 295 __ Pop(rdi); // Function. |
| 297 __ popq(rbp); | 296 __ popq(rbp); |
| 298 | 297 |
| 299 // Load context from the function. | 298 // Load context from the function. |
| 300 __ movp(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); | 299 __ movp(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); |
| 301 | 300 |
| 302 // Get function code. | 301 // Get function code. |
| 303 __ movp(rdx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset)); | 302 __ movp(rdx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset)); |
| 304 __ movp(rdx, FieldOperand(rdx, SharedFunctionInfo::kCodeOffset)); | 303 __ movp(rdx, FieldOperand(rdx, SharedFunctionInfo::kCodeOffset)); |
| 305 __ leap(rdx, FieldOperand(rdx, Code::kHeaderSize)); | 304 __ leap(rdx, FieldOperand(rdx, Code::kHeaderSize)); |
| 306 | 305 |
| 307 // Re-run JSFunction, rdi is function, rsi is context. | 306 // Re-run JSFunction, rdi is function, rsi is context. |
| 308 __ jmp(rdx); | 307 __ jmp(rdx); |
| 309 } | 308 } |
| 310 | 309 |
| 311 const bool Debug::kFrameDropperSupported = true; | 310 const bool LiveEdit::kFrameDropperSupported = true; |
| 312 | 311 |
| 313 #undef __ | 312 #undef __ |
| 314 | 313 |
| 315 } } // namespace v8::internal | 314 } } // namespace v8::internal |
| 316 | 315 |
| 317 #endif // V8_TARGET_ARCH_X64 | 316 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |