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 "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #if V8_TARGET_ARCH_X64 | 7 #if V8_TARGET_ARCH_X64 |
8 | 8 |
9 #include "src/assembler.h" | 9 #include "src/assembler.h" |
10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
11 #include "src/debug.h" | 11 #include "src/debug.h" |
12 | 12 |
13 | 13 |
14 namespace v8 { | 14 namespace v8 { |
15 namespace internal { | 15 namespace internal { |
16 | 16 |
17 bool BreakLocationIterator::IsDebugBreakAtReturn() { | 17 bool BreakLocationIterator::IsDebugBreakAtReturn() { |
18 return Debug::IsDebugBreakAtReturn(rinfo()); | 18 return Debug::IsDebugBreakAtReturn(rinfo()); |
19 } | 19 } |
20 | 20 |
21 | 21 |
22 // Patch the JS frame exit code with a debug break call. See | 22 // Patch the JS frame exit code with a debug break call. See |
23 // CodeGenerator::VisitReturnStatement and VirtualFrame::Exit in codegen-x64.cc | 23 // CodeGenerator::VisitReturnStatement and VirtualFrame::Exit in codegen-x64.cc |
24 // for the precise return instructions sequence. | 24 // for the precise return instructions sequence. |
25 void BreakLocationIterator::SetDebugBreakAtReturn() { | 25 void BreakLocationIterator::SetDebugBreakAtReturn() { |
26 ASSERT(Assembler::kJSReturnSequenceLength >= Assembler::kCallSequenceLength); | 26 DCHECK(Assembler::kJSReturnSequenceLength >= Assembler::kCallSequenceLength); |
27 rinfo()->PatchCodeWithCall( | 27 rinfo()->PatchCodeWithCall( |
28 debug_info_->GetIsolate()->builtins()->Return_DebugBreak()->entry(), | 28 debug_info_->GetIsolate()->builtins()->Return_DebugBreak()->entry(), |
29 Assembler::kJSReturnSequenceLength - Assembler::kCallSequenceLength); | 29 Assembler::kJSReturnSequenceLength - Assembler::kCallSequenceLength); |
30 } | 30 } |
31 | 31 |
32 | 32 |
33 // Restore the JS frame exit code. | 33 // Restore the JS frame exit code. |
34 void BreakLocationIterator::ClearDebugBreakAtReturn() { | 34 void BreakLocationIterator::ClearDebugBreakAtReturn() { |
35 rinfo()->PatchCode(original_rinfo()->pc(), | 35 rinfo()->PatchCode(original_rinfo()->pc(), |
36 Assembler::kJSReturnSequenceLength); | 36 Assembler::kJSReturnSequenceLength); |
37 } | 37 } |
38 | 38 |
39 | 39 |
40 // A debug break in the frame exit code is identified by the JS frame exit code | 40 // A debug break in the frame exit code is identified by the JS frame exit code |
41 // having been patched with a call instruction. | 41 // having been patched with a call instruction. |
42 bool Debug::IsDebugBreakAtReturn(v8::internal::RelocInfo* rinfo) { | 42 bool Debug::IsDebugBreakAtReturn(v8::internal::RelocInfo* rinfo) { |
43 ASSERT(RelocInfo::IsJSReturn(rinfo->rmode())); | 43 DCHECK(RelocInfo::IsJSReturn(rinfo->rmode())); |
44 return rinfo->IsPatchedReturnSequence(); | 44 return rinfo->IsPatchedReturnSequence(); |
45 } | 45 } |
46 | 46 |
47 | 47 |
48 bool BreakLocationIterator::IsDebugBreakAtSlot() { | 48 bool BreakLocationIterator::IsDebugBreakAtSlot() { |
49 ASSERT(IsDebugBreakSlot()); | 49 DCHECK(IsDebugBreakSlot()); |
50 // Check whether the debug break slot instructions have been patched. | 50 // Check whether the debug break slot instructions have been patched. |
51 return rinfo()->IsPatchedDebugBreakSlotSequence(); | 51 return rinfo()->IsPatchedDebugBreakSlotSequence(); |
52 } | 52 } |
53 | 53 |
54 | 54 |
55 void BreakLocationIterator::SetDebugBreakAtSlot() { | 55 void BreakLocationIterator::SetDebugBreakAtSlot() { |
56 ASSERT(IsDebugBreakSlot()); | 56 DCHECK(IsDebugBreakSlot()); |
57 rinfo()->PatchCodeWithCall( | 57 rinfo()->PatchCodeWithCall( |
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 DCHECK(IsDebugBreakSlot()); |
65 rinfo()->PatchCode(original_rinfo()->pc(), Assembler::kDebugBreakSlotLength); | 65 rinfo()->PatchCode(original_rinfo()->pc(), Assembler::kDebugBreakSlotLength); |
66 } | 66 } |
67 | 67 |
68 | 68 |
69 #define __ ACCESS_MASM(masm) | 69 #define __ ACCESS_MASM(masm) |
70 | 70 |
71 | 71 |
72 static void Generate_DebugBreakCallHelper(MacroAssembler* masm, | 72 static void Generate_DebugBreakCallHelper(MacroAssembler* masm, |
73 RegList object_regs, | 73 RegList object_regs, |
74 RegList non_object_regs, | 74 RegList non_object_regs, |
75 bool convert_call_to_jmp) { | 75 bool convert_call_to_jmp) { |
76 // Enter an internal frame. | 76 // Enter an internal frame. |
77 { | 77 { |
78 FrameScope scope(masm, StackFrame::INTERNAL); | 78 FrameScope scope(masm, StackFrame::INTERNAL); |
79 | 79 |
80 // Load padding words on stack. | 80 // Load padding words on stack. |
81 for (int i = 0; i < LiveEdit::kFramePaddingInitialSize; i++) { | 81 for (int i = 0; i < LiveEdit::kFramePaddingInitialSize; i++) { |
82 __ Push(Smi::FromInt(LiveEdit::kFramePaddingValue)); | 82 __ Push(Smi::FromInt(LiveEdit::kFramePaddingValue)); |
83 } | 83 } |
84 __ Push(Smi::FromInt(LiveEdit::kFramePaddingInitialSize)); | 84 __ Push(Smi::FromInt(LiveEdit::kFramePaddingInitialSize)); |
85 | 85 |
86 // Store the registers containing live values on the expression stack to | 86 // Store the registers containing live values on the expression stack to |
87 // 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 |
88 // 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. |
89 ASSERT((object_regs & ~kJSCallerSaved) == 0); | 89 DCHECK((object_regs & ~kJSCallerSaved) == 0); |
90 ASSERT((non_object_regs & ~kJSCallerSaved) == 0); | 90 DCHECK((non_object_regs & ~kJSCallerSaved) == 0); |
91 ASSERT((object_regs & non_object_regs) == 0); | 91 DCHECK((object_regs & non_object_regs) == 0); |
92 for (int i = 0; i < kNumJSCallerSaved; i++) { | 92 for (int i = 0; i < kNumJSCallerSaved; i++) { |
93 int r = JSCallerSavedCode(i); | 93 int r = JSCallerSavedCode(i); |
94 Register reg = { r }; | 94 Register reg = { r }; |
95 ASSERT(!reg.is(kScratchRegister)); | 95 DCHECK(!reg.is(kScratchRegister)); |
96 if ((object_regs & (1 << r)) != 0) { | 96 if ((object_regs & (1 << r)) != 0) { |
97 __ Push(reg); | 97 __ Push(reg); |
98 } | 98 } |
99 if ((non_object_regs & (1 << r)) != 0) { | 99 if ((non_object_regs & (1 << r)) != 0) { |
100 __ PushRegisterAsTwoSmis(reg); | 100 __ PushRegisterAsTwoSmis(reg); |
101 } | 101 } |
102 } | 102 } |
103 | 103 |
104 #ifdef DEBUG | 104 #ifdef DEBUG |
105 __ RecordComment("// Calling from debug break to runtime - come in - over"); | 105 __ RecordComment("// Calling from debug break to runtime - come in - over"); |
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
248 rax.bit(), false); | 248 rax.bit(), false); |
249 } | 249 } |
250 | 250 |
251 | 251 |
252 void DebugCodegen::GenerateSlot(MacroAssembler* masm) { | 252 void DebugCodegen::GenerateSlot(MacroAssembler* masm) { |
253 // Generate enough nop's to make space for a call instruction. | 253 // Generate enough nop's to make space for a call instruction. |
254 Label check_codesize; | 254 Label check_codesize; |
255 __ bind(&check_codesize); | 255 __ bind(&check_codesize); |
256 __ RecordDebugBreakSlot(); | 256 __ RecordDebugBreakSlot(); |
257 __ Nop(Assembler::kDebugBreakSlotLength); | 257 __ Nop(Assembler::kDebugBreakSlotLength); |
258 ASSERT_EQ(Assembler::kDebugBreakSlotLength, | 258 DCHECK_EQ(Assembler::kDebugBreakSlotLength, |
259 masm->SizeOfCodeGeneratedSince(&check_codesize)); | 259 masm->SizeOfCodeGeneratedSince(&check_codesize)); |
260 } | 260 } |
261 | 261 |
262 | 262 |
263 void DebugCodegen::GenerateSlotDebugBreak(MacroAssembler* masm) { | 263 void DebugCodegen::GenerateSlotDebugBreak(MacroAssembler* masm) { |
264 // In the places where a debug break slot is inserted no registers can contain | 264 // In the places where a debug break slot is inserted no registers can contain |
265 // object pointers. | 265 // object pointers. |
266 Generate_DebugBreakCallHelper(masm, 0, 0, true); | 266 Generate_DebugBreakCallHelper(masm, 0, 0, true); |
267 } | 267 } |
268 | 268 |
(...skipping 28 matching lines...) Expand all Loading... |
297 __ jmp(rdx); | 297 __ jmp(rdx); |
298 } | 298 } |
299 | 299 |
300 const bool LiveEdit::kFrameDropperSupported = true; | 300 const bool LiveEdit::kFrameDropperSupported = true; |
301 | 301 |
302 #undef __ | 302 #undef __ |
303 | 303 |
304 } } // namespace v8::internal | 304 } } // namespace v8::internal |
305 | 305 |
306 #endif // V8_TARGET_ARCH_X64 | 306 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |