| Index: src/x64/debug-x64.cc
|
| ===================================================================
|
| --- src/x64/debug-x64.cc (revision 6136)
|
| +++ src/x64/debug-x64.cc (working copy)
|
| @@ -25,7 +25,6 @@
|
| // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
| // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
| -
|
| #include "v8.h"
|
|
|
| #if defined(V8_TARGET_ARCH_X64)
|
| @@ -39,13 +38,61 @@
|
|
|
| #ifdef ENABLE_DEBUGGER_SUPPORT
|
|
|
| +bool BreakLocationIterator::IsDebugBreakAtReturn() {
|
| + return Debug::IsDebugBreakAtReturn(rinfo());
|
| +}
|
| +
|
| +
|
| +// Patch the JS frame exit code with a debug break call. See
|
| +// CodeGenerator::VisitReturnStatement and VirtualFrame::Exit in codegen-x64.cc
|
| +// for the precise return instructions sequence.
|
| +void BreakLocationIterator::SetDebugBreakAtReturn() {
|
| + ASSERT(Assembler::kJSReturnSequenceLength >=
|
| + Assembler::kCallInstructionLength);
|
| + rinfo()->PatchCodeWithCall(Debug::debug_break_return()->entry(),
|
| + Assembler::kJSReturnSequenceLength - Assembler::kCallInstructionLength);
|
| +}
|
| +
|
| +
|
| +// Restore the JS frame exit code.
|
| +void BreakLocationIterator::ClearDebugBreakAtReturn() {
|
| + rinfo()->PatchCode(original_rinfo()->pc(),
|
| + Assembler::kJSReturnSequenceLength);
|
| +}
|
| +
|
| +
|
| +// A debug break in the frame exit code is identified by the JS frame exit code
|
| +// having been patched with a call instruction.
|
| bool Debug::IsDebugBreakAtReturn(v8::internal::RelocInfo* rinfo) {
|
| ASSERT(RelocInfo::IsJSReturn(rinfo->rmode()));
|
| return rinfo->IsPatchedReturnSequence();
|
| }
|
|
|
| +
|
| +bool BreakLocationIterator::IsDebugBreakAtSlot() {
|
| + ASSERT(IsDebugBreakSlot());
|
| + // Check whether the debug break slot instructions have been patched.
|
| + return !Assembler::IsNop(rinfo()->pc());
|
| +}
|
| +
|
| +
|
| +void BreakLocationIterator::SetDebugBreakAtSlot() {
|
| + ASSERT(IsDebugBreakSlot());
|
| + rinfo()->PatchCodeWithCall(
|
| + Debug::debug_break_slot()->entry(),
|
| + Assembler::kDebugBreakSlotLength - Assembler::kCallInstructionLength);
|
| +}
|
| +
|
| +
|
| +void BreakLocationIterator::ClearDebugBreakAtSlot() {
|
| + ASSERT(IsDebugBreakSlot());
|
| + rinfo()->PatchCode(original_rinfo()->pc(), Assembler::kDebugBreakSlotLength);
|
| +}
|
| +
|
| +
|
| #define __ ACCESS_MASM(masm)
|
|
|
| +
|
| static void Generate_DebugBreakCallHelper(MacroAssembler* masm,
|
| RegList object_regs,
|
| RegList non_object_regs,
|
| @@ -55,7 +102,7 @@
|
|
|
| // Store the registers containing live values on the expression stack to
|
| // make sure that these are correctly updated during GC. Non object values
|
| - // are stored as as two smi causing it to be untouched by GC.
|
| + // are stored as as two smis causing it to be untouched by GC.
|
| ASSERT((object_regs & ~kJSCallerSaved) == 0);
|
| ASSERT((non_object_regs & ~kJSCallerSaved) == 0);
|
| ASSERT((object_regs & non_object_regs) == 0);
|
| @@ -126,24 +173,25 @@
|
| }
|
|
|
|
|
| -void Debug::GenerateCallICDebugBreak(MacroAssembler* masm) {
|
| - // Register state for IC call call (from ic-x64.cc)
|
| +void Debug::GenerateLoadICDebugBreak(MacroAssembler* masm) {
|
| + // Register state for IC load call (from ic-x64.cc).
|
| // ----------- S t a t e -------------
|
| - // -- rcx: function name
|
| + // -- rax : receiver
|
| + // -- rcx : name
|
| // -----------------------------------
|
| - Generate_DebugBreakCallHelper(masm, rcx.bit(), 0, false);
|
| + Generate_DebugBreakCallHelper(masm, rax.bit() | rcx.bit(), 0, false);
|
| }
|
|
|
|
|
| -void Debug::GenerateConstructCallDebugBreak(MacroAssembler* masm) {
|
| - // Register state just before return from JS function (from codegen-x64.cc).
|
| - // rax is the actual number of arguments not encoded as a smi, see comment
|
| - // above IC call.
|
| +void Debug::GenerateStoreICDebugBreak(MacroAssembler* masm) {
|
| + // Register state for IC store call (from ic-x64.cc).
|
| // ----------- S t a t e -------------
|
| - // -- rax: number of arguments
|
| + // -- rax : value
|
| + // -- rcx : name
|
| + // -- rdx : receiver
|
| // -----------------------------------
|
| - // The number of arguments in rax is not smi encoded.
|
| - Generate_DebugBreakCallHelper(masm, rdi.bit(), rax.bit(), false);
|
| + Generate_DebugBreakCallHelper(
|
| + masm, rax.bit() | rcx.bit() | rdx.bit(), 0, false);
|
| }
|
|
|
|
|
| @@ -169,34 +217,33 @@
|
| }
|
|
|
|
|
| -void Debug::GenerateLoadICDebugBreak(MacroAssembler* masm) {
|
| - // Register state for IC load call (from ic-x64.cc).
|
| +void Debug::GenerateCallICDebugBreak(MacroAssembler* masm) {
|
| + // Register state for IC call call (from ic-x64.cc)
|
| // ----------- S t a t e -------------
|
| - // -- rax : receiver
|
| - // -- rcx : name
|
| + // -- rcx: function name
|
| // -----------------------------------
|
| - Generate_DebugBreakCallHelper(masm, rax.bit() | rcx.bit(), 0, false);
|
| + Generate_DebugBreakCallHelper(masm, rcx.bit(), 0, false);
|
| }
|
|
|
|
|
| -void Debug::GenerateReturnDebugBreak(MacroAssembler* masm) {
|
| +void Debug::GenerateConstructCallDebugBreak(MacroAssembler* masm) {
|
| // Register state just before return from JS function (from codegen-x64.cc).
|
| + // rax is the actual number of arguments not encoded as a smi, see comment
|
| + // above IC call.
|
| // ----------- S t a t e -------------
|
| - // -- rax: return value
|
| + // -- rax: number of arguments
|
| // -----------------------------------
|
| - Generate_DebugBreakCallHelper(masm, rax.bit(), 0, true);
|
| + // The number of arguments in rax is not smi encoded.
|
| + Generate_DebugBreakCallHelper(masm, rdi.bit(), rax.bit(), false);
|
| }
|
|
|
|
|
| -void Debug::GenerateStoreICDebugBreak(MacroAssembler* masm) {
|
| - // Register state for IC store call (from ic-x64.cc).
|
| +void Debug::GenerateReturnDebugBreak(MacroAssembler* masm) {
|
| + // Register state just before return from JS function (from codegen-x64.cc).
|
| // ----------- S t a t e -------------
|
| - // -- rax : value
|
| - // -- rcx : name
|
| - // -- rdx : receiver
|
| + // -- rax: return value
|
| // -----------------------------------
|
| - Generate_DebugBreakCallHelper(
|
| - masm, rax.bit() | rcx.bit() | rdx.bit(), 0, false);
|
| + Generate_DebugBreakCallHelper(masm, rax.bit(), 0, true);
|
| }
|
|
|
|
|
| @@ -262,49 +309,6 @@
|
|
|
| #undef __
|
|
|
| -
|
| -
|
| -
|
| -void BreakLocationIterator::ClearDebugBreakAtReturn() {
|
| - rinfo()->PatchCode(original_rinfo()->pc(),
|
| - Assembler::kJSReturnSequenceLength);
|
| -}
|
| -
|
| -
|
| -bool BreakLocationIterator::IsDebugBreakAtReturn() {
|
| - return Debug::IsDebugBreakAtReturn(rinfo());
|
| -}
|
| -
|
| -
|
| -void BreakLocationIterator::SetDebugBreakAtReturn() {
|
| - ASSERT(Assembler::kJSReturnSequenceLength >=
|
| - Assembler::kCallInstructionLength);
|
| - rinfo()->PatchCodeWithCall(Debug::debug_break_return()->entry(),
|
| - Assembler::kJSReturnSequenceLength - Assembler::kCallInstructionLength);
|
| -}
|
| -
|
| -
|
| -bool BreakLocationIterator::IsDebugBreakAtSlot() {
|
| - ASSERT(IsDebugBreakSlot());
|
| - // Check whether the debug break slot instructions have been patched.
|
| - return !Assembler::IsNop(rinfo()->pc());
|
| -}
|
| -
|
| -
|
| -void BreakLocationIterator::SetDebugBreakAtSlot() {
|
| - ASSERT(IsDebugBreakSlot());
|
| - rinfo()->PatchCodeWithCall(
|
| - Debug::debug_break_slot()->entry(),
|
| - Assembler::kDebugBreakSlotLength - Assembler::kCallInstructionLength);
|
| -}
|
| -
|
| -
|
| -void BreakLocationIterator::ClearDebugBreakAtSlot() {
|
| - ASSERT(IsDebugBreakSlot());
|
| - rinfo()->PatchCode(original_rinfo()->pc(), Assembler::kDebugBreakSlotLength);
|
| -}
|
| -
|
| -
|
| #endif // ENABLE_DEBUGGER_SUPPORT
|
|
|
| } } // namespace v8::internal
|
|
|