| Index: src/debug.cc
|
| ===================================================================
|
| --- src/debug.cc (revision 4816)
|
| +++ src/debug.cc (working copy)
|
| @@ -129,10 +129,14 @@
|
| ASSERT(statement_position_ >= 0);
|
| }
|
|
|
| - // Check for breakable code target. Look in the original code as setting
|
| - // break points can cause the code targets in the running (debugged) code to
|
| - // be of a different kind than in the original code.
|
| - if (RelocInfo::IsCodeTarget(rmode())) {
|
| + if (IsDebugBreakSlot()) {
|
| + // There is always a possible break point at a debug break slot.
|
| + break_point_++;
|
| + return;
|
| + } else if (RelocInfo::IsCodeTarget(rmode())) {
|
| + // Check for breakable code target. Look in the original code as setting
|
| + // break points can cause the code targets in the running (debugged) code
|
| + // to be of a different kind than in the original code.
|
| Address target = original_rinfo()->target_address();
|
| Code* code = Code::GetCodeFromTargetAddress(target);
|
| if ((code->is_inline_cache_stub() &&
|
| @@ -329,6 +333,9 @@
|
| if (RelocInfo::IsJSReturn(rmode())) {
|
| // Patch the frame exit code with a break point.
|
| SetDebugBreakAtReturn();
|
| + } else if (IsDebugBreakSlot()) {
|
| + // Patch the code in the break slot.
|
| + SetDebugBreakAtSlot();
|
| } else {
|
| // Patch the IC call.
|
| SetDebugBreakAtIC();
|
| @@ -346,6 +353,9 @@
|
| if (RelocInfo::IsJSReturn(rmode())) {
|
| // Restore the frame exit code.
|
| ClearDebugBreakAtReturn();
|
| + } else if (IsDebugBreakSlot()) {
|
| + // Restore the code in the break slot.
|
| + ClearDebugBreakAtSlot();
|
| } else {
|
| // Patch the IC call.
|
| ClearDebugBreakAtIC();
|
| @@ -417,6 +427,8 @@
|
| bool BreakLocationIterator::IsDebugBreak() {
|
| if (RelocInfo::IsJSReturn(rmode())) {
|
| return IsDebugBreakAtReturn();
|
| + } else if (IsDebugBreakSlot()) {
|
| + return IsDebugBreakAtSlot();
|
| } else {
|
| return Debug::IsDebugBreak(rinfo()->target_address());
|
| }
|
| @@ -478,6 +490,11 @@
|
| }
|
|
|
|
|
| +bool BreakLocationIterator::IsDebugBreakSlot() {
|
| + return RelocInfo::DEBUG_BREAK_SLOT == rmode();
|
| +}
|
| +
|
| +
|
| Object* BreakLocationIterator::BreakPointObjects() {
|
| return debug_info_->GetBreakPointObjects(code_position());
|
| }
|
| @@ -573,6 +590,7 @@
|
|
|
| Handle<Context> Debug::debug_context_ = Handle<Context>();
|
| Code* Debug::debug_break_return_ = NULL;
|
| +Code* Debug::debug_break_slot_ = NULL;
|
|
|
|
|
| void ScriptCache::Add(Handle<Script> script) {
|
| @@ -656,6 +674,10 @@
|
| debug_break_return_ =
|
| Builtins::builtin(Builtins::Return_DebugBreak);
|
| ASSERT(debug_break_return_->IsCode());
|
| + // Get code to handle debug break in debug break slots.
|
| + debug_break_slot_ =
|
| + Builtins::builtin(Builtins::Slot_DebugBreak);
|
| + ASSERT(debug_break_slot_->IsCode());
|
| }
|
| }
|
|
|
| @@ -824,6 +846,7 @@
|
|
|
| void Debug::Iterate(ObjectVisitor* v) {
|
| v->VisitPointer(BitCast<Object**, Code**>(&(debug_break_return_)));
|
| + v->VisitPointer(BitCast<Object**, Code**>(&(debug_break_slot_)));
|
| }
|
|
|
|
|
| @@ -1631,16 +1654,21 @@
|
| // break point is still active after processing the break point.
|
| Address addr = frame->pc() - Assembler::kCallTargetAddressOffset;
|
|
|
| - // Check if the location is at JS exit.
|
| + // Check if the location is at JS exit or debug break slot.
|
| bool at_js_return = false;
|
| bool break_at_js_return_active = false;
|
| + bool at_debug_break_slot = false;
|
| RelocIterator it(debug_info->code());
|
| - while (!it.done()) {
|
| + while (!it.done() && !at_js_return && !at_debug_break_slot) {
|
| if (RelocInfo::IsJSReturn(it.rinfo()->rmode())) {
|
| at_js_return = (it.rinfo()->pc() ==
|
| addr - Assembler::kPatchReturnSequenceAddressOffset);
|
| break_at_js_return_active = it.rinfo()->IsPatchedReturnSequence();
|
| }
|
| + if (RelocInfo::IsDebugBreakSlot(it.rinfo()->rmode())) {
|
| + at_debug_break_slot = (it.rinfo()->pc() ==
|
| + addr - Assembler::kPatchDebugBreakSlotAddressOffset);
|
| + }
|
| it.next();
|
| }
|
|
|
| @@ -1657,25 +1685,30 @@
|
| // Move back to where the call instruction sequence started.
|
| thread_local_.after_break_target_ =
|
| addr - Assembler::kPatchReturnSequenceAddressOffset;
|
| - } else {
|
| - // Check if there still is a debug break call at the target address. If the
|
| - // break point has been removed it will have disappeared. If it have
|
| - // disappeared don't try to look in the original code as the running code
|
| - // will have the right address. This takes care of the case where the last
|
| - // break point is removed from the function and therefore no "original code"
|
| - // is available. If the debug break call is still there find the address in
|
| - // the original code.
|
| - if (IsDebugBreak(Assembler::target_address_at(addr))) {
|
| - // If the break point is still there find the call address which was
|
| - // overwritten in the original code by the call to DebugBreakXXX.
|
| + } else if (at_debug_break_slot) {
|
| + // Address of where the debug break slot starts.
|
| + addr = addr - Assembler::kPatchDebugBreakSlotAddressOffset;
|
|
|
| - // Find the corresponding address in the original code.
|
| - addr += original_code->instruction_start() - code->instruction_start();
|
| - }
|
| + // Continue just after the slot.
|
| + thread_local_.after_break_target_ = addr + Assembler::kDebugBreakSlotLength;
|
| + } else if (IsDebugBreak(Assembler::target_address_at(addr))) {
|
| + // We now know that there is still a debug break call at the target address,
|
| + // so the break point is still there and the original code will hold the
|
| + // address to jump to in order to complete the call which is replaced by a
|
| + // call to DebugBreakXXX.
|
|
|
| + // Find the corresponding address in the original code.
|
| + addr += original_code->instruction_start() - code->instruction_start();
|
| +
|
| // Install jump to the call address in the original code. This will be the
|
| // call which was overwritten by the call to DebugBreakXXX.
|
| thread_local_.after_break_target_ = Assembler::target_address_at(addr);
|
| + } else {
|
| + // There is no longer a break point present. Don't try to look in the
|
| + // original code as the running code will have the right address. This takes
|
| + // care of the case where the last break point is removed from the function
|
| + // and therefore no "original code" is available.
|
| + thread_local_.after_break_target_ = Assembler::target_address_at(addr);
|
| }
|
| }
|
|
|
|
|