Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2009 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 21 matching lines...) Expand all Loading... | |
| 32 #include "debug.h" | 32 #include "debug.h" |
| 33 | 33 |
| 34 | 34 |
| 35 namespace v8 { | 35 namespace v8 { |
| 36 namespace internal { | 36 namespace internal { |
| 37 | 37 |
| 38 #ifdef ENABLE_DEBUGGER_SUPPORT | 38 #ifdef ENABLE_DEBUGGER_SUPPORT |
| 39 | 39 |
| 40 bool Debug::IsDebugBreakAtReturn(v8::internal::RelocInfo* rinfo) { | 40 bool Debug::IsDebugBreakAtReturn(v8::internal::RelocInfo* rinfo) { |
| 41 ASSERT(RelocInfo::IsJSReturn(rinfo->rmode())); | 41 ASSERT(RelocInfo::IsJSReturn(rinfo->rmode())); |
| 42 // 11th byte of patch is 0x49, 11th byte of JS return is 0xCC (int3). | 42 // 11th byte of patch is 0x49 (REX.WB byte of computed jump/call to r10), |
| 43 // 11th byte of JS return is 0xCC (int3). | |
| 43 ASSERT(*(rinfo->pc() + 10) == 0x49 || *(rinfo->pc() + 10) == 0xCC); | 44 ASSERT(*(rinfo->pc() + 10) == 0x49 || *(rinfo->pc() + 10) == 0xCC); |
| 44 return (*(rinfo->pc() + 10) == 0x49); | 45 return (*(rinfo->pc() + 10) != 0xCC); |
| 45 } | 46 } |
| 46 | 47 |
| 47 void Debug::GenerateCallICDebugBreak(MacroAssembler* masm) { | 48 #define __ ACCESS_MASM(masm) |
| 48 masm->int3(); // UNIMPLEMENTED | 49 |
| 50 static void Generate_DebugBreakCallHelper(MacroAssembler* masm, | |
| 51 RegList pointer_regs, | |
| 52 bool convert_call_to_jmp) { | |
| 53 // Save the content of all general purpose registers in memory. This copy in | |
| 54 // memory is later pushed onto the JS expression stack for the fake JS frame | |
| 55 // generated and also to the C frame generated on top of that. In the JS | |
| 56 // frame ONLY the registers containing pointers will be pushed on the | |
| 57 // expression stack. This causes the GC to update these pointers so that | |
| 58 // they will have the correct value when returning from the debugger. | |
| 59 __ SaveRegistersToMemory(kJSCallerSaved); | |
| 60 | |
| 61 // Enter an internal frame. | |
| 62 __ EnterInternalFrame(); | |
| 63 | |
| 64 // Store the registers containing object pointers on the expression stack to | |
| 65 // make sure that these are correctly updated during GC. | |
| 66 __ PushRegistersFromMemory(pointer_regs); | |
| 67 | |
| 68 #ifdef DEBUG | |
| 69 __ RecordComment("// Calling from debug break to runtime - come in - over"); | |
| 70 #endif | |
| 71 __ xor_(rax, rax); // No arguments (argc == 0). | |
| 72 __ movq(rbx, ExternalReference::debug_break()); | |
| 73 | |
| 74 CEntryDebugBreakStub ceb; | |
| 75 __ CallStub(&ceb); | |
| 76 | |
| 77 // Restore the register values containing object pointers from the expression | |
| 78 // stack in the reverse order as they where pushed. | |
| 79 __ PopRegistersToMemory(pointer_regs); | |
| 80 | |
| 81 // Get rid of the internal frame. | |
| 82 __ LeaveInternalFrame(); | |
| 83 | |
| 84 // If this call did not replace a call but patched other code then there will | |
| 85 // be an unwanted return address left on the stack. Here we get rid of that. | |
| 86 if (convert_call_to_jmp) { | |
| 87 __ pop(rax); | |
| 88 } | |
| 89 | |
| 90 // Finally restore all registers. | |
| 91 __ RestoreRegistersFromMemory(kJSCallerSaved); | |
| 92 | |
| 93 // Now that the break point has been handled, resume normal execution by | |
| 94 // jumping to the target address intended by the caller and that was | |
| 95 // overwritten by the address of DebugBreakXXX. | |
|
William Hesse
2009/08/19 08:44:00
Is there really a function called DebugBreakXXX?
Lasse Reichstein
2009/08/19 10:12:32
No, it was meant to refer to the DebugBreak<somet
| |
| 96 ExternalReference after_break_target = | |
| 97 ExternalReference(Debug_Address::AfterBreakTarget()); | |
| 98 __ movq(kScratchRegister, after_break_target); | |
| 99 __ jmp(Operand(kScratchRegister, 0)); | |
| 49 } | 100 } |
| 50 | 101 |
| 51 void Debug::GenerateConstructCallDebugBreak(MacroAssembler* masm) { | 102 |
| 52 masm->int3(); // UNIMPLEMENTED | 103 void Debug::GenerateCallICDebugBreak(MacroAssembler* masm) { |
| 104 // Register state for keyed IC call call (from ic-x64.cc) | |
| 105 // ----------- S t a t e ------------- | |
| 106 // -- rax: number of arguments | |
| 107 // ----------------------------------- | |
| 108 // The number of arguments in rax is not smi encoded. | |
| 109 Generate_DebugBreakCallHelper(masm, 0, false); | |
| 53 } | 110 } |
| 54 | 111 |
| 55 void Debug::GenerateKeyedLoadICDebugBreak(MacroAssembler* masm) { | 112 |
| 56 masm->int3(); // UNIMPLEMENTED | 113 void Debug::GenerateConstructCallDebugBreak(MacroAssembler* masm) { |
| 114 // Register state just before return from JS function (from codegen-x64.cc). | |
| 115 // rax is the actual number of arguments not encoded as a smi, see comment | |
| 116 // above IC call. | |
| 117 // ----------- S t a t e ------------- | |
| 118 // -- rax: number of arguments | |
| 119 // ----------------------------------- | |
| 120 // The number of arguments in rax is not smi encoded. | |
| 121 Generate_DebugBreakCallHelper(masm, 0, false); | |
| 57 } | 122 } |
| 58 | 123 |
| 59 void Debug::GenerateKeyedStoreICDebugBreak(MacroAssembler* masm) { | 124 |
| 60 masm->int3(); // UNIMPLEMENTED | 125 void Debug::GenerateKeyedLoadICDebugBreak(MacroAssembler* masm) { |
| 126 // Register state for keyed IC load call (from ic-x64.cc). | |
| 127 // ----------- S t a t e ------------- | |
| 128 // No registers used on entry. | |
| 129 // ----------------------------------- | |
| 130 Generate_DebugBreakCallHelper(masm, 0, false); | |
| 61 } | 131 } |
| 62 | 132 |
| 63 void Debug::GenerateLoadICDebugBreak(MacroAssembler* masm) { | 133 |
| 64 masm->int3(); // UNIMPLEMENTED | 134 void Debug::GenerateKeyedStoreICDebugBreak(MacroAssembler* masm) { |
| 135 // Register state for keyed IC load call (from ic-x64.cc). | |
| 136 // ----------- S t a t e ------------- | |
| 137 // -- rax : value | |
| 138 // ----------------------------------- | |
| 139 // Register rax contains an object that needs to be pushed on the | |
| 140 // expression stack of the fake JS frame. | |
| 141 Generate_DebugBreakCallHelper(masm, rax.bit(), false); | |
| 65 } | 142 } |
| 66 | 143 |
| 67 void Debug::GenerateReturnDebugBreak(MacroAssembler* masm) { | 144 |
| 68 masm->int3(); // UNIMPLEMENTED | 145 void Debug::GenerateLoadICDebugBreak(MacroAssembler* masm) { |
| 146 // Register state for IC load call (from ic-x64.cc). | |
| 147 // ----------- S t a t e ------------- | |
| 148 // -- rcx : name | |
| 149 // ----------------------------------- | |
| 150 Generate_DebugBreakCallHelper(masm, rcx.bit(), false); | |
| 69 } | 151 } |
| 70 | 152 |
| 71 void Debug::GenerateReturnDebugBreakEntry(MacroAssembler* masm) { | 153 |
| 72 masm->int3(); // UNIMPLEMENTED | 154 void Debug::GenerateReturnDebugBreak(MacroAssembler* masm) { |
| 155 // Register state just before return from JS function (from codegen-x64.cc). | |
| 156 // ----------- S t a t e ------------- | |
| 157 // -- rax: return value | |
| 158 // ----------------------------------- | |
| 159 Generate_DebugBreakCallHelper(masm, rax.bit(), true); | |
| 73 } | 160 } |
| 74 | 161 |
| 75 void Debug::GenerateStoreICDebugBreak(MacroAssembler* masm) { | 162 |
| 76 masm->int3(); // UNIMPLEMENTED | 163 void Debug::GenerateReturnDebugBreakEntry(MacroAssembler* masm) { |
| 164 // OK to clobber rbx as we are returning from a JS function in the code | |
| 165 // generated by X64CodeGenerator::ExitJSFrame. | |
|
Søren Thygesen Gjesse
2009/08/18 13:10:44
Please remove any reference to X64CodeGenerator::E
Lasse Reichstein
2009/08/19 07:07:55
Changed to refer to GenerateReturnSequence, and sa
| |
| 166 ExternalReference debug_break_return = | |
| 167 ExternalReference(Debug_Address::DebugBreakReturn()); | |
| 168 __ movq(rbx, debug_break_return); | |
| 169 __ movq(rbx, Operand(rbx, 0)); | |
| 170 __ addq(rbx, Immediate(Code::kHeaderSize - kHeapObjectTag)); | |
| 171 __ jmp(rbx); | |
| 77 } | 172 } |
| 78 | 173 |
| 79 void Debug::GenerateStubNoRegistersDebugBreak(MacroAssembler* masm) { | 174 |
| 80 masm->int3(); // UNIMPLEMENTED | 175 void Debug::GenerateStoreICDebugBreak(MacroAssembler* masm) { |
| 176 // REgister state for IC store call (from ic-x64.cc). | |
| 177 // ----------- S t a t e ------------- | |
| 178 // -- rax : value | |
| 179 // -- rcx : name | |
| 180 // ----------------------------------- | |
| 181 Generate_DebugBreakCallHelper(masm, rax.bit() | rcx.bit(), false); | |
| 81 } | 182 } |
| 82 | 183 |
| 83 void BreakLocationIterator::ClearDebugBreakAtReturn() { | 184 |
| 84 // TODO(X64): Implement this when we start setting Debug breaks. | 185 void Debug::GenerateStubNoRegistersDebugBreak(MacroAssembler* masm) { |
| 85 UNIMPLEMENTED(); | 186 // Register state for stub CallFunction (from CallFunctionStub in ic-x64.cc). |
| 187 // ----------- S t a t e ------------- | |
| 188 // No registers used on entry. | |
| 189 // ----------------------------------- | |
| 190 Generate_DebugBreakCallHelper(masm, 0, false); | |
| 86 } | 191 } |
| 87 | 192 |
| 88 bool BreakLocationIterator::IsDebugBreakAtReturn() { | 193 |
| 89 // TODO(X64): Implement this when we start setting Debug breaks. | 194 #undef __ |
| 90 UNIMPLEMENTED(); | 195 |
| 91 return false; | 196 |
| 197 void BreakLocationIterator::ClearDebugBreakAtReturn() { | |
| 198 rinfo()->PatchCode(original_rinfo()->pc(), | |
| 199 Debug::kX64JSReturnSequenceLength); | |
| 92 } | 200 } |
| 93 | 201 |
| 202 | |
| 203 bool BreakLocationIterator::IsDebugBreakAtReturn() { | |
| 204 return Debug::IsDebugBreakAtReturn(rinfo()); | |
| 205 } | |
| 206 | |
| 207 | |
| 94 void BreakLocationIterator::SetDebugBreakAtReturn() { | 208 void BreakLocationIterator::SetDebugBreakAtReturn() { |
| 95 UNIMPLEMENTED(); | 209 ASSERT(Debug::kX64JSReturnSequenceLength >= Debug::kX64CallInstructionLength); |
| 210 rinfo()->PatchCodeWithCall(Debug::debug_break_return_entry()->entry(), | |
| 211 Debug::kX64JSReturnSequenceLength - Debug::kX64CallInstructionLength); | |
| 96 } | 212 } |
| 97 | 213 |
| 98 #endif // ENABLE_DEBUGGER_SUPPORT | 214 #endif // ENABLE_DEBUGGER_SUPPORT |
| 99 | 215 |
| 100 } } // namespace v8::internal | 216 } } // namespace v8::internal |
| OLD | NEW |