| 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" | 
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 62   PatchCodeWithCall( | 62   PatchCodeWithCall( | 
| 63       pc(), debug_info_->GetIsolate()->builtins()->Slot_DebugBreak()->entry(), | 63       pc(), debug_info_->GetIsolate()->builtins()->Slot_DebugBreak()->entry(), | 
| 64       Assembler::kDebugBreakSlotLength - Assembler::kCallSequenceLength); | 64       Assembler::kDebugBreakSlotLength - Assembler::kCallSequenceLength); | 
| 65 } | 65 } | 
| 66 | 66 | 
| 67 | 67 | 
| 68 #define __ ACCESS_MASM(masm) | 68 #define __ ACCESS_MASM(masm) | 
| 69 | 69 | 
| 70 | 70 | 
| 71 static void Generate_DebugBreakCallHelper(MacroAssembler* masm, | 71 static void Generate_DebugBreakCallHelper(MacroAssembler* masm, | 
| 72                                           RegList object_regs, | 72                                           RegList object_regs) { | 
| 73                                           RegList non_object_regs, |  | 
| 74                                           bool convert_call_to_jmp) { |  | 
| 75   // Enter an internal frame. | 73   // Enter an internal frame. | 
| 76   { | 74   { | 
| 77     FrameScope scope(masm, StackFrame::INTERNAL); | 75     FrameScope scope(masm, StackFrame::INTERNAL); | 
| 78 | 76 | 
| 79     // Load padding words on stack. | 77     // Load padding words on stack. | 
| 80     for (int i = 0; i < LiveEdit::kFramePaddingInitialSize; i++) { | 78     for (int i = 0; i < LiveEdit::kFramePaddingInitialSize; i++) { | 
| 81       __ Push(Smi::FromInt(LiveEdit::kFramePaddingValue)); | 79       __ Push(Smi::FromInt(LiveEdit::kFramePaddingValue)); | 
| 82     } | 80     } | 
| 83     __ Push(Smi::FromInt(LiveEdit::kFramePaddingInitialSize)); | 81     __ Push(Smi::FromInt(LiveEdit::kFramePaddingInitialSize)); | 
| 84 | 82 | 
| 85     // Store the registers containing live values on the expression stack to | 83     // Store the registers containing live values on the expression stack to | 
| 86     // make sure that these are correctly updated during GC. Non object values | 84     // make sure that these are correctly updated during GC. Non object values | 
| 87     // are stored as as two smis causing it to be untouched by GC. | 85     // are stored as as two smis causing it to be untouched by GC. | 
| 88     DCHECK((object_regs & ~kJSCallerSaved) == 0); | 86     DCHECK((object_regs & ~kJSCallerSaved) == 0); | 
| 89     DCHECK((non_object_regs & ~kJSCallerSaved) == 0); |  | 
| 90     DCHECK((object_regs & non_object_regs) == 0); |  | 
| 91     for (int i = 0; i < kNumJSCallerSaved; i++) { | 87     for (int i = 0; i < kNumJSCallerSaved; i++) { | 
| 92       int r = JSCallerSavedCode(i); | 88       int r = JSCallerSavedCode(i); | 
| 93       Register reg = { r }; | 89       Register reg = { r }; | 
| 94       DCHECK(!reg.is(kScratchRegister)); | 90       DCHECK(!reg.is(kScratchRegister)); | 
| 95       if ((object_regs & (1 << r)) != 0) { | 91       if ((object_regs & (1 << r)) != 0) { | 
| 96         __ Push(reg); | 92         __ Push(reg); | 
| 97       } | 93       } | 
| 98       if ((non_object_regs & (1 << r)) != 0) { |  | 
| 99         __ PushRegisterAsTwoSmis(reg); |  | 
| 100       } |  | 
| 101     } | 94     } | 
| 102 | 95 | 
| 103 #ifdef DEBUG | 96 #ifdef DEBUG | 
| 104     __ RecordComment("// Calling from debug break to runtime - come in - over"); | 97     __ RecordComment("// Calling from debug break to runtime - come in - over"); | 
| 105 #endif | 98 #endif | 
| 106     __ Set(rax, 0);  // No arguments (argc == 0). | 99     __ Set(rax, 0);  // No arguments (argc == 0). | 
| 107     __ Move(rbx, ExternalReference::debug_break(masm->isolate())); | 100     __ Move(rbx, ExternalReference::debug_break(masm->isolate())); | 
| 108 | 101 | 
| 109     CEntryStub ceb(masm->isolate(), 1); | 102     CEntryStub ceb(masm->isolate(), 1); | 
| 110     __ CallStub(&ceb); | 103     __ CallStub(&ceb); | 
| 111 | 104 | 
| 112     // Restore the register values from the expression stack. | 105     // Restore the register values from the expression stack. | 
| 113     for (int i = kNumJSCallerSaved - 1; i >= 0; i--) { | 106     for (int i = kNumJSCallerSaved - 1; i >= 0; i--) { | 
| 114       int r = JSCallerSavedCode(i); | 107       int r = JSCallerSavedCode(i); | 
| 115       Register reg = { r }; | 108       Register reg = { r }; | 
| 116       if (FLAG_debug_code) { | 109       if (FLAG_debug_code) { | 
| 117         __ Set(reg, kDebugZapValue); | 110         __ Set(reg, kDebugZapValue); | 
| 118       } | 111       } | 
| 119       if ((object_regs & (1 << r)) != 0) { | 112       if ((object_regs & (1 << r)) != 0) { | 
| 120         __ Pop(reg); | 113         __ Pop(reg); | 
| 121       } | 114       } | 
| 122       // Reconstruct the 64-bit value from two smis. |  | 
| 123       if ((non_object_regs & (1 << r)) != 0) { |  | 
| 124         __ PopRegisterAsTwoSmis(reg); |  | 
| 125       } |  | 
| 126     } | 115     } | 
| 127 | 116 | 
| 128     // Read current padding counter and skip corresponding number of words. | 117     // Read current padding counter and skip corresponding number of words. | 
| 129     __ Pop(kScratchRegister); | 118     __ Pop(kScratchRegister); | 
| 130     __ SmiToInteger32(kScratchRegister, kScratchRegister); | 119     __ SmiToInteger32(kScratchRegister, kScratchRegister); | 
| 131     __ leap(rsp, Operand(rsp, kScratchRegister, times_pointer_size, 0)); | 120     __ leap(rsp, Operand(rsp, kScratchRegister, times_pointer_size, 0)); | 
| 132 | 121 | 
| 133     // Get rid of the internal frame. | 122     // Get rid of the internal frame. | 
| 134   } | 123   } | 
| 135 | 124 | 
| 136   // If this call did not replace a call but patched other code then there will | 125   // This call did not replace a call , so there will be an unwanted | 
| 137   // be an unwanted return address left on the stack. Here we get rid of that. | 126   // return address left on the stack. Here we get rid of that. | 
| 138   if (convert_call_to_jmp) { | 127   __ addp(rsp, Immediate(kPCOnStackSize)); | 
| 139     __ addp(rsp, Immediate(kPCOnStackSize)); |  | 
| 140   } |  | 
| 141 | 128 | 
| 142   // Now that the break point has been handled, resume normal execution by | 129   // Now that the break point has been handled, resume normal execution by | 
| 143   // jumping to the target address intended by the caller and that was | 130   // jumping to the target address intended by the caller and that was | 
| 144   // overwritten by the address of DebugBreakXXX. | 131   // overwritten by the address of DebugBreakXXX. | 
| 145   ExternalReference after_break_target = | 132   ExternalReference after_break_target = | 
| 146       ExternalReference::debug_after_break_target_address(masm->isolate()); | 133       ExternalReference::debug_after_break_target_address(masm->isolate()); | 
| 147   __ Move(kScratchRegister, after_break_target); | 134   __ Move(kScratchRegister, after_break_target); | 
| 148   __ Jump(Operand(kScratchRegister, 0)); | 135   __ Jump(Operand(kScratchRegister, 0)); | 
| 149 } | 136 } | 
| 150 | 137 | 
| 151 | 138 | 
| 152 void DebugCodegen::GenerateCallICStubDebugBreak(MacroAssembler* masm) { |  | 
| 153   // Register state for CallICStub |  | 
| 154   // ----------- S t a t e ------------- |  | 
| 155   //  -- rdx    : type feedback slot (smi) |  | 
| 156   //  -- rdi    : function |  | 
| 157   // ----------------------------------- |  | 
| 158   Generate_DebugBreakCallHelper(masm, rdx.bit() | rdi.bit(), 0, false); |  | 
| 159 } |  | 
| 160 |  | 
| 161 |  | 
| 162 void DebugCodegen::GenerateReturnDebugBreak(MacroAssembler* masm) { | 139 void DebugCodegen::GenerateReturnDebugBreak(MacroAssembler* masm) { | 
| 163   // Register state just before return from JS function (from codegen-x64.cc). | 140   // Register state just before return from JS function (from codegen-x64.cc). | 
| 164   // ----------- S t a t e ------------- | 141   // ----------- S t a t e ------------- | 
| 165   //  -- rax: return value | 142   //  -- rax: return value | 
| 166   // ----------------------------------- | 143   // ----------------------------------- | 
| 167   Generate_DebugBreakCallHelper(masm, rax.bit(), 0, true); | 144   Generate_DebugBreakCallHelper(masm, rax.bit()); | 
| 168 } | 145 } | 
| 169 | 146 | 
| 170 | 147 | 
| 171 void DebugCodegen::GenerateCallFunctionStubDebugBreak(MacroAssembler* masm) { |  | 
| 172   // Register state for CallFunctionStub (from code-stubs-x64.cc). |  | 
| 173   // ----------- S t a t e ------------- |  | 
| 174   //  -- rdi : function |  | 
| 175   // ----------------------------------- |  | 
| 176   Generate_DebugBreakCallHelper(masm, rdi.bit(), 0, false); |  | 
| 177 } |  | 
| 178 |  | 
| 179 |  | 
| 180 void DebugCodegen::GenerateCallConstructStubDebugBreak(MacroAssembler* masm) { |  | 
| 181   // Register state for CallConstructStub (from code-stubs-x64.cc). |  | 
| 182   // rax is the actual number of arguments not encoded as a smi, see comment |  | 
| 183   // above IC call. |  | 
| 184   // ----------- S t a t e ------------- |  | 
| 185   //  -- rax: number of arguments |  | 
| 186   // ----------------------------------- |  | 
| 187   // The number of arguments in rax is not smi encoded. |  | 
| 188   Generate_DebugBreakCallHelper(masm, rdi.bit(), rax.bit(), false); |  | 
| 189 } |  | 
| 190 |  | 
| 191 |  | 
| 192 void DebugCodegen::GenerateCallConstructStubRecordDebugBreak( |  | 
| 193     MacroAssembler* masm) { |  | 
| 194   // Register state for CallConstructStub (from code-stubs-x64.cc). |  | 
| 195   // rax is the actual number of arguments not encoded as a smi, see comment |  | 
| 196   // above IC call. |  | 
| 197   // ----------- S t a t e ------------- |  | 
| 198   //  -- rax: number of arguments |  | 
| 199   //  -- rbx: feedback array |  | 
| 200   //  -- rdx: feedback slot (smi) |  | 
| 201   // ----------------------------------- |  | 
| 202   // The number of arguments in rax is not smi encoded. |  | 
| 203   Generate_DebugBreakCallHelper(masm, rbx.bit() | rdx.bit() | rdi.bit(), |  | 
| 204                                 rax.bit(), false); |  | 
| 205 } |  | 
| 206 |  | 
| 207 |  | 
| 208 void DebugCodegen::GenerateSlot(MacroAssembler* masm) { | 148 void DebugCodegen::GenerateSlot(MacroAssembler* masm) { | 
| 209   // Generate enough nop's to make space for a call instruction. | 149   // Generate enough nop's to make space for a call instruction. | 
| 210   Label check_codesize; | 150   Label check_codesize; | 
| 211   __ bind(&check_codesize); | 151   __ bind(&check_codesize); | 
| 212   __ RecordDebugBreakSlot(); |  | 
| 213   __ Nop(Assembler::kDebugBreakSlotLength); | 152   __ Nop(Assembler::kDebugBreakSlotLength); | 
| 214   DCHECK_EQ(Assembler::kDebugBreakSlotLength, | 153   DCHECK_EQ(Assembler::kDebugBreakSlotLength, | 
| 215             masm->SizeOfCodeGeneratedSince(&check_codesize)); | 154             masm->SizeOfCodeGeneratedSince(&check_codesize)); | 
| 216 } | 155 } | 
| 217 | 156 | 
| 218 | 157 | 
| 219 void DebugCodegen::GenerateSlotDebugBreak(MacroAssembler* masm) { | 158 void DebugCodegen::GenerateSlotDebugBreak(MacroAssembler* masm) { | 
| 220   // In the places where a debug break slot is inserted no registers can contain | 159   // In the places where a debug break slot is inserted no registers can contain | 
| 221   // object pointers. | 160   // object pointers. | 
| 222   Generate_DebugBreakCallHelper(masm, 0, 0, true); | 161   Generate_DebugBreakCallHelper(masm, 0); | 
| 223 } | 162 } | 
| 224 | 163 | 
| 225 | 164 | 
| 226 void DebugCodegen::GeneratePlainReturnLiveEdit(MacroAssembler* masm) { | 165 void DebugCodegen::GeneratePlainReturnLiveEdit(MacroAssembler* masm) { | 
| 227   masm->ret(0); | 166   masm->ret(0); | 
| 228 } | 167 } | 
| 229 | 168 | 
| 230 | 169 | 
| 231 void DebugCodegen::GenerateFrameDropperLiveEdit(MacroAssembler* masm) { | 170 void DebugCodegen::GenerateFrameDropperLiveEdit(MacroAssembler* masm) { | 
| 232   ExternalReference restarter_frame_function_slot = | 171   ExternalReference restarter_frame_function_slot = | 
| (...skipping 21 matching lines...) Expand all  Loading... | 
| 254 } | 193 } | 
| 255 | 194 | 
| 256 const bool LiveEdit::kFrameDropperSupported = true; | 195 const bool LiveEdit::kFrameDropperSupported = true; | 
| 257 | 196 | 
| 258 #undef __ | 197 #undef __ | 
| 259 | 198 | 
| 260 }  // namespace internal | 199 }  // namespace internal | 
| 261 }  // namespace v8 | 200 }  // namespace v8 | 
| 262 | 201 | 
| 263 #endif  // V8_TARGET_ARCH_X64 | 202 #endif  // V8_TARGET_ARCH_X64 | 
| OLD | NEW | 
|---|