Chromium Code Reviews| 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/debug/debug.h" | 5 #include "src/debug/debug.h" |
| 6 | 6 |
| 7 #include "src/api.h" | 7 #include "src/api.h" |
| 8 #include "src/arguments.h" | 8 #include "src/arguments.h" |
| 9 #include "src/bootstrapper.h" | 9 #include "src/bootstrapper.h" |
| 10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 55 // occured. | 55 // occured. |
| 56 if (context.is_null()) return v8::Local<v8::Context>(); | 56 if (context.is_null()) return v8::Local<v8::Context>(); |
| 57 Handle<Context> native_context(context->native_context()); | 57 Handle<Context> native_context(context->native_context()); |
| 58 return v8::Utils::ToLocal(native_context); | 58 return v8::Utils::ToLocal(native_context); |
| 59 } | 59 } |
| 60 | 60 |
| 61 | 61 |
| 62 BreakLocation::BreakLocation(Handle<DebugInfo> debug_info, RelocInfo* rinfo, | 62 BreakLocation::BreakLocation(Handle<DebugInfo> debug_info, RelocInfo* rinfo, |
| 63 int position, int statement_position) | 63 int position, int statement_position) |
| 64 : debug_info_(debug_info), | 64 : debug_info_(debug_info), |
| 65 pc_offset_(static_cast<int>(rinfo->pc() - debug_info->code()->entry())), | 65 code_offset_(static_cast<int>(rinfo->pc() - debug_info->code()->entry())), |
| 66 rmode_(rinfo->rmode()), | 66 rmode_(rinfo->rmode()), |
| 67 data_(rinfo->data()), | 67 data_(rinfo->data()), |
| 68 position_(position), | 68 position_(position), |
| 69 statement_position_(statement_position) {} | 69 statement_position_(statement_position) {} |
| 70 | 70 |
| 71 | 71 |
| 72 BreakLocation::Iterator::Iterator(Handle<DebugInfo> debug_info, | 72 BreakLocation::Iterator::Iterator(Handle<DebugInfo> debug_info, |
| 73 BreakLocatorType type) | 73 BreakLocatorType type) |
| 74 : debug_info_(debug_info), | 74 : debug_info_(debug_info), |
| 75 reloc_iterator_(debug_info->code(), GetModeMask(type)), | 75 reloc_iterator_(debug_info->code(), GetModeMask(type)), |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 137 } | 137 } |
| 138 | 138 |
| 139 break; | 139 break; |
| 140 } | 140 } |
| 141 break_index_++; | 141 break_index_++; |
| 142 } | 142 } |
| 143 | 143 |
| 144 | 144 |
| 145 // Find the break point at the supplied address, or the closest one before | 145 // Find the break point at the supplied address, or the closest one before |
| 146 // the address. | 146 // the address. |
| 147 BreakLocation BreakLocation::FromAddress(Handle<DebugInfo> debug_info, | 147 BreakLocation BreakLocation::FromCodeOffset(Handle<DebugInfo> debug_info, |
| 148 Address pc) { | 148 int offset) { |
| 149 Iterator it(debug_info, ALL_BREAK_LOCATIONS); | 149 Iterator it(debug_info, ALL_BREAK_LOCATIONS); |
| 150 it.SkipTo(BreakIndexFromAddress(debug_info, pc)); | 150 it.SkipTo(BreakIndexFromCodeOffset(debug_info, offset)); |
| 151 return it.GetBreakLocation(); | 151 return it.GetBreakLocation(); |
| 152 } | 152 } |
| 153 | 153 |
| 154 | 154 |
| 155 BreakLocation BreakLocation::FromFrame(Handle<DebugInfo> debug_info, | |
| 156 JavaScriptFrame* frame) { | |
| 157 // Code offset to the instruction after the current one, possibly a break | |
| 158 // location as well. So the "- 1" to exclude it from the search. | |
| 159 Code* code = frame->LookupCode(); | |
| 160 int code_offset = frame->pc() - code->instruction_start(); | |
| 161 return FromCodeOffset(debug_info, code_offset - 1); | |
| 162 } | |
| 163 | |
| 164 | |
| 155 // Find the break point at the supplied address, or the closest one before | 165 // Find the break point at the supplied address, or the closest one before |
| 156 // the address. | 166 // the address. |
| 157 void BreakLocation::FromAddressSameStatement(Handle<DebugInfo> debug_info, | 167 void BreakLocation::FromCodeOffsetSameStatement( |
| 158 Address pc, | 168 Handle<DebugInfo> debug_info, int offset, List<BreakLocation>* result_out) { |
| 159 List<BreakLocation>* result_out) { | 169 int break_index = BreakIndexFromCodeOffset(debug_info, offset); |
| 160 int break_index = BreakIndexFromAddress(debug_info, pc); | |
| 161 Iterator it(debug_info, ALL_BREAK_LOCATIONS); | 170 Iterator it(debug_info, ALL_BREAK_LOCATIONS); |
| 162 it.SkipTo(break_index); | 171 it.SkipTo(break_index); |
| 163 int statement_position = it.statement_position(); | 172 int statement_position = it.statement_position(); |
| 164 while (!it.Done() && it.statement_position() == statement_position) { | 173 while (!it.Done() && it.statement_position() == statement_position) { |
| 165 result_out->Add(it.GetBreakLocation()); | 174 result_out->Add(it.GetBreakLocation()); |
| 166 it.Next(); | 175 it.Next(); |
| 167 } | 176 } |
| 168 } | 177 } |
| 169 | 178 |
| 170 | 179 |
| 171 int BreakLocation::BreakIndexFromAddress(Handle<DebugInfo> debug_info, | 180 int BreakLocation::BreakIndexFromCodeOffset(Handle<DebugInfo> debug_info, |
| 172 Address pc) { | 181 int offset) { |
| 173 // Run through all break points to locate the one closest to the address. | 182 // Run through all break points to locate the one closest to the address. |
| 174 int closest_break = 0; | 183 int closest_break = 0; |
| 175 int distance = kMaxInt; | 184 int distance = kMaxInt; |
| 185 Code* code = debug_info->code(); | |
| 186 DCHECK(0 <= offset && offset < code->instruction_size()); | |
| 187 Address pc = debug_info->code()->instruction_start() + offset; | |
| 176 for (Iterator it(debug_info, ALL_BREAK_LOCATIONS); !it.Done(); it.Next()) { | 188 for (Iterator it(debug_info, ALL_BREAK_LOCATIONS); !it.Done(); it.Next()) { |
| 177 // Check if this break point is closer that what was previously found. | 189 // Check if this break point is closer that what was previously found. |
| 178 if (it.pc() <= pc && pc - it.pc() < distance) { | 190 if (it.pc() <= pc && pc - it.pc() < distance) { |
| 179 closest_break = it.break_index(); | 191 closest_break = it.break_index(); |
| 180 distance = static_cast<int>(pc - it.pc()); | 192 distance = static_cast<int>(pc - it.pc()); |
| 181 // Check whether we can't get any closer. | 193 // Check whether we can't get any closer. |
| 182 if (distance == 0) break; | 194 if (distance == 0) break; |
| 183 } | 195 } |
| 184 } | 196 } |
| 185 return closest_break; | 197 return closest_break; |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 215 return it.GetBreakLocation(); | 227 return it.GetBreakLocation(); |
| 216 } | 228 } |
| 217 | 229 |
| 218 | 230 |
| 219 void BreakLocation::SetBreakPoint(Handle<Object> break_point_object) { | 231 void BreakLocation::SetBreakPoint(Handle<Object> break_point_object) { |
| 220 // If there is not already a real break point here patch code with debug | 232 // If there is not already a real break point here patch code with debug |
| 221 // break. | 233 // break. |
| 222 if (!HasBreakPoint()) SetDebugBreak(); | 234 if (!HasBreakPoint()) SetDebugBreak(); |
| 223 DCHECK(IsDebugBreak() || IsDebuggerStatement()); | 235 DCHECK(IsDebugBreak() || IsDebuggerStatement()); |
| 224 // Set the break point information. | 236 // Set the break point information. |
| 225 DebugInfo::SetBreakPoint(debug_info_, pc_offset_, position_, | 237 DebugInfo::SetBreakPoint(debug_info_, code_offset_, position_, |
| 226 statement_position_, break_point_object); | 238 statement_position_, break_point_object); |
| 227 } | 239 } |
| 228 | 240 |
| 229 | 241 |
| 230 void BreakLocation::ClearBreakPoint(Handle<Object> break_point_object) { | 242 void BreakLocation::ClearBreakPoint(Handle<Object> break_point_object) { |
| 231 // Clear the break point information. | 243 // Clear the break point information. |
| 232 DebugInfo::ClearBreakPoint(debug_info_, pc_offset_, break_point_object); | 244 DebugInfo::ClearBreakPoint(debug_info_, code_offset_, break_point_object); |
| 233 // If there are no more break points here remove the debug break. | 245 // If there are no more break points here remove the debug break. |
| 234 if (!HasBreakPoint()) { | 246 if (!HasBreakPoint()) { |
| 235 ClearDebugBreak(); | 247 ClearDebugBreak(); |
| 236 DCHECK(!IsDebugBreak()); | 248 DCHECK(!IsDebugBreak()); |
| 237 } | 249 } |
| 238 } | 250 } |
| 239 | 251 |
| 240 | 252 |
| 241 void BreakLocation::SetOneShot() { | 253 void BreakLocation::SetOneShot() { |
| 242 // Debugger statement always calls debugger. No need to modify it. | 254 // Debugger statement always calls debugger. No need to modify it. |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 300 | 312 |
| 301 | 313 |
| 302 bool BreakLocation::IsDebugBreak() const { | 314 bool BreakLocation::IsDebugBreak() const { |
| 303 if (IsDebuggerStatement()) return false; | 315 if (IsDebuggerStatement()) return false; |
| 304 DCHECK(IsDebugBreakSlot()); | 316 DCHECK(IsDebugBreakSlot()); |
| 305 return rinfo().IsPatchedDebugBreakSlotSequence(); | 317 return rinfo().IsPatchedDebugBreakSlotSequence(); |
| 306 } | 318 } |
| 307 | 319 |
| 308 | 320 |
| 309 Handle<Object> BreakLocation::BreakPointObjects() const { | 321 Handle<Object> BreakLocation::BreakPointObjects() const { |
| 310 return debug_info_->GetBreakPointObjects(pc_offset_); | 322 return debug_info_->GetBreakPointObjects(code_offset_); |
| 311 } | 323 } |
| 312 | 324 |
| 313 | 325 |
| 314 void DebugFeatureTracker::Track(DebugFeatureTracker::Feature feature) { | 326 void DebugFeatureTracker::Track(DebugFeatureTracker::Feature feature) { |
| 315 uint32_t mask = 1 << feature; | 327 uint32_t mask = 1 << feature; |
| 316 // Only count one sample per feature and isolate. | 328 // Only count one sample per feature and isolate. |
| 317 if (bitfield_ & mask) return; | 329 if (bitfield_ & mask) return; |
| 318 isolate_->counters()->debug_feature_usage()->AddSample(feature); | 330 isolate_->counters()->debug_feature_usage()->AddSample(feature); |
| 319 bitfield_ |= mask; | 331 bitfield_ |= mask; |
| 320 } | 332 } |
| (...skipping 356 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 677 DebugInfoListNode* node = debug_info_list_; | 689 DebugInfoListNode* node = debug_info_list_; |
| 678 while (node != NULL) { | 690 while (node != NULL) { |
| 679 Handle<Object> result = | 691 Handle<Object> result = |
| 680 DebugInfo::FindBreakPointInfo(node->debug_info(), break_point_object); | 692 DebugInfo::FindBreakPointInfo(node->debug_info(), break_point_object); |
| 681 if (!result->IsUndefined()) { | 693 if (!result->IsUndefined()) { |
| 682 // Get information in the break point. | 694 // Get information in the break point. |
| 683 Handle<BreakPointInfo> break_point_info = | 695 Handle<BreakPointInfo> break_point_info = |
| 684 Handle<BreakPointInfo>::cast(result); | 696 Handle<BreakPointInfo>::cast(result); |
| 685 Handle<DebugInfo> debug_info = node->debug_info(); | 697 Handle<DebugInfo> debug_info = node->debug_info(); |
| 686 | 698 |
| 687 // Find the break point and clear it. | 699 BreakLocation location = BreakLocation::FromCodeOffset( |
| 688 Address pc = | 700 debug_info, break_point_info->code_offset()); |
| 689 debug_info->code()->entry() + break_point_info->code_position(); | |
| 690 | |
| 691 BreakLocation location = BreakLocation::FromAddress(debug_info, pc); | |
| 692 location.ClearBreakPoint(break_point_object); | 701 location.ClearBreakPoint(break_point_object); |
| 693 | 702 |
| 694 // If there are no more break points left remove the debug info for this | 703 // If there are no more break points left remove the debug info for this |
| 695 // function. | 704 // function. |
| 696 if (debug_info->GetBreakPointCount() == 0) { | 705 if (debug_info->GetBreakPointCount() == 0) { |
| 697 RemoveDebugInfoAndClearFromShared(debug_info); | 706 RemoveDebugInfoAndClearFromShared(debug_info); |
| 698 } | 707 } |
| 699 | 708 |
| 700 return; | 709 return; |
| 701 } | 710 } |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 852 FrameSummary summary = GetFirstFrameSummary(frame); | 861 FrameSummary summary = GetFirstFrameSummary(frame); |
| 853 Handle<JSFunction> function(summary.function()); | 862 Handle<JSFunction> function(summary.function()); |
| 854 Handle<SharedFunctionInfo> shared(function->shared()); | 863 Handle<SharedFunctionInfo> shared(function->shared()); |
| 855 if (!EnsureDebugInfo(shared, function)) { | 864 if (!EnsureDebugInfo(shared, function)) { |
| 856 // Return if ensuring debug info failed. | 865 // Return if ensuring debug info failed. |
| 857 return; | 866 return; |
| 858 } | 867 } |
| 859 | 868 |
| 860 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); | 869 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); |
| 861 // Refresh frame summary if the code has been recompiled for debugging. | 870 // Refresh frame summary if the code has been recompiled for debugging. |
| 862 if (shared->code() != *summary.code()) summary = GetFirstFrameSummary(frame); | 871 if (shared->AbstractCode() != *summary.abstract_code()) { |
| 872 summary = GetFirstFrameSummary(frame); | |
| 873 } | |
| 863 | 874 |
| 864 // PC points to the instruction after the current one, possibly a break | 875 // PC points to the instruction after the current one, possibly a break |
| 865 // location as well. So the "- 1" to exclude it from the search. | 876 // location as well. So the "- 1" to exclude it from the search. |
| 866 BreakLocation location = BreakLocation::FromFrame(debug_info, &summary); | 877 BreakLocation location = |
| 878 BreakLocation::FromCodeOffset(debug_info, summary.code_offset() - 1); | |
| 867 | 879 |
| 868 // At a return statement we will step out either way. | 880 // At a return statement we will step out either way. |
| 869 if (location.IsReturn()) step_action = StepOut; | 881 if (location.IsReturn()) step_action = StepOut; |
| 870 | 882 |
| 883 Address pc = debug_info->code()->instruction_start() + summary.code_offset(); | |
| 871 thread_local_.last_statement_position_ = | 884 thread_local_.last_statement_position_ = |
| 872 debug_info->code()->SourceStatementPosition(summary.pc()); | 885 debug_info->code()->SourceStatementPosition(pc); |
| 873 thread_local_.last_fp_ = frame->UnpaddedFP(); | 886 thread_local_.last_fp_ = frame->UnpaddedFP(); |
| 874 | 887 |
| 875 switch (step_action) { | 888 switch (step_action) { |
| 876 case StepNone: | 889 case StepNone: |
| 877 UNREACHABLE(); | 890 UNREACHABLE(); |
| 878 break; | 891 break; |
| 879 case StepOut: | 892 case StepOut: |
| 880 // Advance to caller frame. | 893 // Advance to caller frame. |
| 881 frames_it.Advance(); | 894 frames_it.Advance(); |
| 882 // Skip native and extension functions on the stack. | 895 // Skip native and extension functions on the stack. |
| (...skipping 591 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1474 List<int>* results_out) { | 1487 List<int>* results_out) { |
| 1475 FrameSummary summary = GetFirstFrameSummary(frame); | 1488 FrameSummary summary = GetFirstFrameSummary(frame); |
| 1476 | 1489 |
| 1477 Handle<JSFunction> fun = Handle<JSFunction>(summary.function()); | 1490 Handle<JSFunction> fun = Handle<JSFunction>(summary.function()); |
| 1478 Handle<SharedFunctionInfo> shared = Handle<SharedFunctionInfo>(fun->shared()); | 1491 Handle<SharedFunctionInfo> shared = Handle<SharedFunctionInfo>(fun->shared()); |
| 1479 | 1492 |
| 1480 if (!EnsureDebugInfo(shared, fun)) return; | 1493 if (!EnsureDebugInfo(shared, fun)) return; |
| 1481 | 1494 |
| 1482 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); | 1495 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); |
| 1483 // Refresh frame summary if the code has been recompiled for debugging. | 1496 // Refresh frame summary if the code has been recompiled for debugging. |
| 1484 if (shared->code() != *summary.code()) summary = GetFirstFrameSummary(frame); | 1497 if (shared->AbstractCode() != *summary.abstract_code()) { |
| 1498 summary = GetFirstFrameSummary(frame); | |
| 1499 } | |
| 1485 | 1500 |
| 1486 // Find range of break points starting from the break point where execution | 1501 // Find range of break points starting from the break point where execution |
| 1487 // has stopped. | 1502 // has stopped. |
|
rmcilroy
2016/01/22 19:16:34
Nit - could you add a comment on the -1 here too.
Yang
2016/01/28 09:09:53
Done.
| |
| 1488 Address call_pc = summary.pc() - 1; | 1503 int call_offset = summary.code_offset() - 1; |
| 1489 List<BreakLocation> locations; | 1504 List<BreakLocation> locations; |
| 1490 BreakLocation::FromAddressSameStatement(debug_info, call_pc, &locations); | 1505 BreakLocation::FromCodeOffsetSameStatement(debug_info, call_offset, |
| 1506 &locations); | |
| 1491 | 1507 |
| 1492 for (BreakLocation location : locations) { | 1508 for (BreakLocation location : locations) { |
| 1493 if (location.pc() <= summary.pc()) { | 1509 if (location.code_offset() <= summary.code_offset()) { |
| 1494 // The break point is near our pc. Could be a step-in possibility, | 1510 // The break point is near our pc. Could be a step-in possibility, |
| 1495 // that is currently taken by active debugger call. | 1511 // that is currently taken by active debugger call. |
| 1496 if (break_frame_id() == StackFrame::NO_ID) { | 1512 if (break_frame_id() == StackFrame::NO_ID) { |
| 1497 continue; // We are not stepping. | 1513 continue; // We are not stepping. |
| 1498 } else { | 1514 } else { |
| 1499 JavaScriptFrameIterator frame_it(isolate_, break_frame_id()); | 1515 JavaScriptFrameIterator frame_it(isolate_, break_frame_id()); |
| 1500 // If our frame is a top frame and we are stepping, we can do step-in | 1516 // If our frame is a top frame and we are stepping, we can do step-in |
| 1501 // at this place. | 1517 // at this place. |
| 1502 if (frame_it.frame()->id() != frame_id) continue; | 1518 if (frame_it.frame()->id() != frame_id) continue; |
| 1503 } | 1519 } |
| (...skipping 923 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2427 } | 2443 } |
| 2428 | 2444 |
| 2429 | 2445 |
| 2430 void LockingCommandMessageQueue::Clear() { | 2446 void LockingCommandMessageQueue::Clear() { |
| 2431 base::LockGuard<base::Mutex> lock_guard(&mutex_); | 2447 base::LockGuard<base::Mutex> lock_guard(&mutex_); |
| 2432 queue_.Clear(); | 2448 queue_.Clear(); |
| 2433 } | 2449 } |
| 2434 | 2450 |
| 2435 } // namespace internal | 2451 } // namespace internal |
| 2436 } // namespace v8 | 2452 } // namespace v8 |
| OLD | NEW |