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 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
51 | 51 |
52 static v8::Local<v8::Context> GetDebugEventContext(Isolate* isolate) { | 52 static v8::Local<v8::Context> GetDebugEventContext(Isolate* isolate) { |
53 Handle<Context> context = isolate->debug()->debugger_entry()->GetContext(); | 53 Handle<Context> context = isolate->debug()->debugger_entry()->GetContext(); |
54 // Isolate::context() may have been NULL when "script collected" event | 54 // Isolate::context() may have been NULL when "script collected" event |
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 | |
62 BreakLocation::BreakLocation(Handle<DebugInfo> debug_info, RelocInfo* rinfo, | 61 BreakLocation::BreakLocation(Handle<DebugInfo> debug_info, RelocInfo* rinfo, |
63 int position, int statement_position) | 62 int position, int statement_position) |
64 : debug_info_(debug_info), | 63 : debug_info_(debug_info), |
65 pc_offset_(static_cast<int>(rinfo->pc() - debug_info->code()->entry())), | 64 code_offset_(static_cast<int>(rinfo->pc() - debug_info->code()->entry())), |
66 rmode_(rinfo->rmode()), | 65 rmode_(rinfo->rmode()), |
67 data_(rinfo->data()), | 66 data_(rinfo->data()), |
68 position_(position), | 67 position_(position), |
69 statement_position_(statement_position) {} | 68 statement_position_(statement_position) {} |
70 | 69 |
71 | |
72 BreakLocation::Iterator::Iterator(Handle<DebugInfo> debug_info, | 70 BreakLocation::Iterator::Iterator(Handle<DebugInfo> debug_info, |
73 BreakLocatorType type) | 71 BreakLocatorType type) |
74 : debug_info_(debug_info), | 72 : debug_info_(debug_info), |
75 reloc_iterator_(debug_info->code(), GetModeMask(type)), | 73 reloc_iterator_(debug_info->code(), GetModeMask(type)), |
76 break_index_(-1), | 74 break_index_(-1), |
77 position_(1), | 75 position_(1), |
78 statement_position_(1) { | 76 statement_position_(1) { |
79 if (!Done()) Next(); | 77 if (!Done()) Next(); |
80 } | 78 } |
81 | 79 |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
137 } | 135 } |
138 | 136 |
139 break; | 137 break; |
140 } | 138 } |
141 break_index_++; | 139 break_index_++; |
142 } | 140 } |
143 | 141 |
144 | 142 |
145 // Find the break point at the supplied address, or the closest one before | 143 // Find the break point at the supplied address, or the closest one before |
146 // the address. | 144 // the address. |
147 BreakLocation BreakLocation::FromAddress(Handle<DebugInfo> debug_info, | 145 BreakLocation BreakLocation::FromCodeOffset(Handle<DebugInfo> debug_info, |
148 Address pc) { | 146 int offset) { |
149 Iterator it(debug_info, ALL_BREAK_LOCATIONS); | 147 Iterator it(debug_info, ALL_BREAK_LOCATIONS); |
150 it.SkipTo(BreakIndexFromAddress(debug_info, pc)); | 148 it.SkipTo(BreakIndexFromCodeOffset(debug_info, offset)); |
151 return it.GetBreakLocation(); | 149 return it.GetBreakLocation(); |
152 } | 150 } |
153 | 151 |
| 152 BreakLocation BreakLocation::FromFrame(Handle<DebugInfo> debug_info, |
| 153 JavaScriptFrame* frame) { |
| 154 // Code offset to the instruction after the current one, possibly a break |
| 155 // location as well. So the "- 1" to exclude it from the search. |
| 156 Code* code = frame->LookupCode(); |
| 157 int code_offset = static_cast<int>(frame->pc() - code->instruction_start()); |
| 158 return FromCodeOffset(debug_info, code_offset - 1); |
| 159 } |
154 | 160 |
155 // Find the break point at the supplied address, or the closest one before | 161 // Find the break point at the supplied address, or the closest one before |
156 // the address. | 162 // the address. |
157 void BreakLocation::FromAddressSameStatement(Handle<DebugInfo> debug_info, | 163 void BreakLocation::FromCodeOffsetSameStatement( |
158 Address pc, | 164 Handle<DebugInfo> debug_info, int offset, List<BreakLocation>* result_out) { |
159 List<BreakLocation>* result_out) { | 165 int break_index = BreakIndexFromCodeOffset(debug_info, offset); |
160 int break_index = BreakIndexFromAddress(debug_info, pc); | |
161 Iterator it(debug_info, ALL_BREAK_LOCATIONS); | 166 Iterator it(debug_info, ALL_BREAK_LOCATIONS); |
162 it.SkipTo(break_index); | 167 it.SkipTo(break_index); |
163 int statement_position = it.statement_position(); | 168 int statement_position = it.statement_position(); |
164 while (!it.Done() && it.statement_position() == statement_position) { | 169 while (!it.Done() && it.statement_position() == statement_position) { |
165 result_out->Add(it.GetBreakLocation()); | 170 result_out->Add(it.GetBreakLocation()); |
166 it.Next(); | 171 it.Next(); |
167 } | 172 } |
168 } | 173 } |
169 | 174 |
170 | 175 |
171 // Find all break locations with the given statement position. | |
172 void BreakLocation::AllForStatementPosition(Handle<DebugInfo> debug_info, | 176 void BreakLocation::AllForStatementPosition(Handle<DebugInfo> debug_info, |
173 int statement_position, | 177 int statement_position, |
174 List<BreakLocation>* result_out) { | 178 List<BreakLocation>* result_out) { |
175 for (Iterator it(debug_info, ALL_BREAK_LOCATIONS); !it.Done(); it.Next()) { | 179 for (Iterator it(debug_info, ALL_BREAK_LOCATIONS); !it.Done(); it.Next()) { |
176 if (it.statement_position() == statement_position) { | 180 if (it.statement_position() == statement_position) { |
177 result_out->Add(it.GetBreakLocation()); | 181 result_out->Add(it.GetBreakLocation()); |
178 } | 182 } |
179 } | 183 } |
180 } | 184 } |
181 | 185 |
182 | 186 int BreakLocation::BreakIndexFromCodeOffset(Handle<DebugInfo> debug_info, |
183 int BreakLocation::BreakIndexFromAddress(Handle<DebugInfo> debug_info, | 187 int offset) { |
184 Address pc) { | |
185 // Run through all break points to locate the one closest to the address. | 188 // Run through all break points to locate the one closest to the address. |
186 int closest_break = 0; | 189 int closest_break = 0; |
187 int distance = kMaxInt; | 190 int distance = kMaxInt; |
| 191 Code* code = debug_info->code(); |
| 192 DCHECK(0 <= offset && offset < code->instruction_size()); |
| 193 Address pc = code->instruction_start() + offset; |
188 for (Iterator it(debug_info, ALL_BREAK_LOCATIONS); !it.Done(); it.Next()) { | 194 for (Iterator it(debug_info, ALL_BREAK_LOCATIONS); !it.Done(); it.Next()) { |
189 // Check if this break point is closer that what was previously found. | 195 // Check if this break point is closer that what was previously found. |
190 if (it.pc() <= pc && pc - it.pc() < distance) { | 196 if (it.pc() <= pc && pc - it.pc() < distance) { |
191 closest_break = it.break_index(); | 197 closest_break = it.break_index(); |
192 distance = static_cast<int>(pc - it.pc()); | 198 distance = static_cast<int>(pc - it.pc()); |
193 // Check whether we can't get any closer. | 199 // Check whether we can't get any closer. |
194 if (distance == 0) break; | 200 if (distance == 0) break; |
195 } | 201 } |
196 } | 202 } |
197 return closest_break; | 203 return closest_break; |
(...skipping 29 matching lines...) Expand all Loading... |
227 return it.GetBreakLocation(); | 233 return it.GetBreakLocation(); |
228 } | 234 } |
229 | 235 |
230 | 236 |
231 void BreakLocation::SetBreakPoint(Handle<Object> break_point_object) { | 237 void BreakLocation::SetBreakPoint(Handle<Object> break_point_object) { |
232 // If there is not already a real break point here patch code with debug | 238 // If there is not already a real break point here patch code with debug |
233 // break. | 239 // break. |
234 if (!HasBreakPoint()) SetDebugBreak(); | 240 if (!HasBreakPoint()) SetDebugBreak(); |
235 DCHECK(IsDebugBreak() || IsDebuggerStatement()); | 241 DCHECK(IsDebugBreak() || IsDebuggerStatement()); |
236 // Set the break point information. | 242 // Set the break point information. |
237 DebugInfo::SetBreakPoint(debug_info_, pc_offset_, position_, | 243 DebugInfo::SetBreakPoint(debug_info_, code_offset_, position_, |
238 statement_position_, break_point_object); | 244 statement_position_, break_point_object); |
239 } | 245 } |
240 | 246 |
241 | 247 |
242 void BreakLocation::ClearBreakPoint(Handle<Object> break_point_object) { | 248 void BreakLocation::ClearBreakPoint(Handle<Object> break_point_object) { |
243 // Clear the break point information. | 249 // Clear the break point information. |
244 DebugInfo::ClearBreakPoint(debug_info_, pc_offset_, break_point_object); | 250 DebugInfo::ClearBreakPoint(debug_info_, code_offset_, break_point_object); |
245 // If there are no more break points here remove the debug break. | 251 // If there are no more break points here remove the debug break. |
246 if (!HasBreakPoint()) { | 252 if (!HasBreakPoint()) { |
247 ClearDebugBreak(); | 253 ClearDebugBreak(); |
248 DCHECK(!IsDebugBreak()); | 254 DCHECK(!IsDebugBreak()); |
249 } | 255 } |
250 } | 256 } |
251 | 257 |
252 | 258 |
253 void BreakLocation::SetOneShot() { | 259 void BreakLocation::SetOneShot() { |
254 // Debugger statement always calls debugger. No need to modify it. | 260 // Debugger statement always calls debugger. No need to modify it. |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
312 | 318 |
313 | 319 |
314 bool BreakLocation::IsDebugBreak() const { | 320 bool BreakLocation::IsDebugBreak() const { |
315 if (IsDebuggerStatement()) return false; | 321 if (IsDebuggerStatement()) return false; |
316 DCHECK(IsDebugBreakSlot()); | 322 DCHECK(IsDebugBreakSlot()); |
317 return rinfo().IsPatchedDebugBreakSlotSequence(); | 323 return rinfo().IsPatchedDebugBreakSlotSequence(); |
318 } | 324 } |
319 | 325 |
320 | 326 |
321 Handle<Object> BreakLocation::BreakPointObjects() const { | 327 Handle<Object> BreakLocation::BreakPointObjects() const { |
322 return debug_info_->GetBreakPointObjects(pc_offset_); | 328 return debug_info_->GetBreakPointObjects(code_offset_); |
323 } | 329 } |
324 | 330 |
325 | 331 |
326 void DebugFeatureTracker::Track(DebugFeatureTracker::Feature feature) { | 332 void DebugFeatureTracker::Track(DebugFeatureTracker::Feature feature) { |
327 uint32_t mask = 1 << feature; | 333 uint32_t mask = 1 << feature; |
328 // Only count one sample per feature and isolate. | 334 // Only count one sample per feature and isolate. |
329 if (bitfield_ & mask) return; | 335 if (bitfield_ & mask) return; |
330 isolate_->counters()->debug_feature_usage()->AddSample(feature); | 336 isolate_->counters()->debug_feature_usage()->AddSample(feature); |
331 bitfield_ |= mask; | 337 bitfield_ |= mask; |
332 } | 338 } |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
479 case StepNone: | 485 case StepNone: |
480 return; | 486 return; |
481 case StepOut: | 487 case StepOut: |
482 // Step out has not reached the target frame yet. | 488 // Step out has not reached the target frame yet. |
483 if (current_fp < target_fp) return; | 489 if (current_fp < target_fp) return; |
484 break; | 490 break; |
485 case StepNext: | 491 case StepNext: |
486 // Step next should not break in a deeper frame. | 492 // Step next should not break in a deeper frame. |
487 if (current_fp < target_fp) return; | 493 if (current_fp < target_fp) return; |
488 // Fall through. | 494 // Fall through. |
489 case StepIn: | 495 case StepIn: { |
| 496 int offset = |
| 497 static_cast<int>(frame->pc() - location.code()->instruction_start()); |
490 step_break = location.IsReturn() || (current_fp != last_fp) || | 498 step_break = location.IsReturn() || (current_fp != last_fp) || |
491 (thread_local_.last_statement_position_ != | 499 (thread_local_.last_statement_position_ != |
492 location.code()->SourceStatementPosition(frame->pc())); | 500 location.code()->SourceStatementPosition(offset)); |
493 break; | 501 break; |
| 502 } |
494 case StepFrame: | 503 case StepFrame: |
495 step_break = current_fp != last_fp; | 504 step_break = current_fp != last_fp; |
496 break; | 505 break; |
497 } | 506 } |
498 | 507 |
499 // Clear all current stepping setup. | 508 // Clear all current stepping setup. |
500 ClearStepping(); | 509 ClearStepping(); |
501 | 510 |
502 if (step_break) { | 511 if (step_break) { |
503 // Notify the debug event listeners. | 512 // Notify the debug event listeners. |
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
698 DebugInfoListNode* node = debug_info_list_; | 707 DebugInfoListNode* node = debug_info_list_; |
699 while (node != NULL) { | 708 while (node != NULL) { |
700 Handle<Object> result = | 709 Handle<Object> result = |
701 DebugInfo::FindBreakPointInfo(node->debug_info(), break_point_object); | 710 DebugInfo::FindBreakPointInfo(node->debug_info(), break_point_object); |
702 if (!result->IsUndefined()) { | 711 if (!result->IsUndefined()) { |
703 // Get information in the break point. | 712 // Get information in the break point. |
704 Handle<BreakPointInfo> break_point_info = | 713 Handle<BreakPointInfo> break_point_info = |
705 Handle<BreakPointInfo>::cast(result); | 714 Handle<BreakPointInfo>::cast(result); |
706 Handle<DebugInfo> debug_info = node->debug_info(); | 715 Handle<DebugInfo> debug_info = node->debug_info(); |
707 | 716 |
708 // Find the break point and clear it. | 717 BreakLocation location = BreakLocation::FromCodeOffset( |
709 Address pc = | 718 debug_info, break_point_info->code_offset()); |
710 debug_info->code()->entry() + break_point_info->code_position(); | |
711 | |
712 BreakLocation location = BreakLocation::FromAddress(debug_info, pc); | |
713 location.ClearBreakPoint(break_point_object); | 719 location.ClearBreakPoint(break_point_object); |
714 | 720 |
715 // If there are no more break points left remove the debug info for this | 721 // If there are no more break points left remove the debug info for this |
716 // function. | 722 // function. |
717 if (debug_info->GetBreakPointCount() == 0) { | 723 if (debug_info->GetBreakPointCount() == 0) { |
718 RemoveDebugInfoAndClearFromShared(debug_info); | 724 RemoveDebugInfoAndClearFromShared(debug_info); |
719 } | 725 } |
720 | 726 |
721 return; | 727 return; |
722 } | 728 } |
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
873 FrameSummary summary = GetFirstFrameSummary(frame); | 879 FrameSummary summary = GetFirstFrameSummary(frame); |
874 Handle<JSFunction> function(summary.function()); | 880 Handle<JSFunction> function(summary.function()); |
875 Handle<SharedFunctionInfo> shared(function->shared()); | 881 Handle<SharedFunctionInfo> shared(function->shared()); |
876 if (!EnsureDebugInfo(shared, function)) { | 882 if (!EnsureDebugInfo(shared, function)) { |
877 // Return if ensuring debug info failed. | 883 // Return if ensuring debug info failed. |
878 return; | 884 return; |
879 } | 885 } |
880 | 886 |
881 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); | 887 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); |
882 // Refresh frame summary if the code has been recompiled for debugging. | 888 // Refresh frame summary if the code has been recompiled for debugging. |
883 if (shared->code() != *summary.code()) summary = GetFirstFrameSummary(frame); | 889 if (AbstractCode::cast(shared->code()) != *summary.abstract_code()) { |
| 890 summary = GetFirstFrameSummary(frame); |
| 891 } |
884 | 892 |
885 // PC points to the instruction after the current one, possibly a break | 893 // PC points to the instruction after the current one, possibly a break |
886 // location as well. So the "- 1" to exclude it from the search. | 894 // location as well. So the "- 1" to exclude it from the search. |
887 BreakLocation location = BreakLocation::FromFrame(debug_info, &summary); | 895 BreakLocation location = |
| 896 BreakLocation::FromCodeOffset(debug_info, summary.code_offset() - 1); |
888 | 897 |
889 // At a return statement we will step out either way. | 898 // At a return statement we will step out either way. |
890 if (location.IsReturn()) step_action = StepOut; | 899 if (location.IsReturn()) step_action = StepOut; |
891 | 900 |
892 thread_local_.last_statement_position_ = | 901 thread_local_.last_statement_position_ = |
893 debug_info->code()->SourceStatementPosition(summary.pc()); | 902 debug_info->code()->SourceStatementPosition(summary.code_offset()); |
894 thread_local_.last_fp_ = frame->UnpaddedFP(); | 903 thread_local_.last_fp_ = frame->UnpaddedFP(); |
895 | 904 |
896 switch (step_action) { | 905 switch (step_action) { |
897 case StepNone: | 906 case StepNone: |
898 UNREACHABLE(); | 907 UNREACHABLE(); |
899 break; | 908 break; |
900 case StepOut: | 909 case StepOut: |
901 // Advance to caller frame. | 910 // Advance to caller frame. |
902 frames_it.Advance(); | 911 frames_it.Advance(); |
903 // Skip native and extension functions on the stack. | 912 // Skip native and extension functions on the stack. |
(...skipping 591 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1495 List<int>* results_out) { | 1504 List<int>* results_out) { |
1496 FrameSummary summary = GetFirstFrameSummary(frame); | 1505 FrameSummary summary = GetFirstFrameSummary(frame); |
1497 | 1506 |
1498 Handle<JSFunction> fun = Handle<JSFunction>(summary.function()); | 1507 Handle<JSFunction> fun = Handle<JSFunction>(summary.function()); |
1499 Handle<SharedFunctionInfo> shared = Handle<SharedFunctionInfo>(fun->shared()); | 1508 Handle<SharedFunctionInfo> shared = Handle<SharedFunctionInfo>(fun->shared()); |
1500 | 1509 |
1501 if (!EnsureDebugInfo(shared, fun)) return; | 1510 if (!EnsureDebugInfo(shared, fun)) return; |
1502 | 1511 |
1503 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); | 1512 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); |
1504 // Refresh frame summary if the code has been recompiled for debugging. | 1513 // Refresh frame summary if the code has been recompiled for debugging. |
1505 if (shared->code() != *summary.code()) summary = GetFirstFrameSummary(frame); | 1514 if (AbstractCode::cast(shared->code()) != *summary.abstract_code()) { |
| 1515 summary = GetFirstFrameSummary(frame); |
| 1516 } |
1506 | 1517 |
1507 // Find range of break points starting from the break point where execution | 1518 // Find range of break points starting from the break point where execution |
1508 // has stopped. | 1519 // has stopped. The code offset points to the instruction after the current |
1509 Address call_pc = summary.pc() - 1; | 1520 // possibly a break location, too. Subtract one to exclude it from the search. |
| 1521 int call_offset = summary.code_offset() - 1; |
1510 List<BreakLocation> locations; | 1522 List<BreakLocation> locations; |
1511 BreakLocation::FromAddressSameStatement(debug_info, call_pc, &locations); | 1523 BreakLocation::FromCodeOffsetSameStatement(debug_info, call_offset, |
| 1524 &locations); |
1512 | 1525 |
1513 for (BreakLocation location : locations) { | 1526 for (BreakLocation location : locations) { |
1514 if (location.pc() <= summary.pc()) { | 1527 if (location.code_offset() <= summary.code_offset()) { |
1515 // The break point is near our pc. Could be a step-in possibility, | 1528 // The break point is near our pc. Could be a step-in possibility, |
1516 // that is currently taken by active debugger call. | 1529 // that is currently taken by active debugger call. |
1517 if (break_frame_id() == StackFrame::NO_ID) { | 1530 if (break_frame_id() == StackFrame::NO_ID) { |
1518 continue; // We are not stepping. | 1531 continue; // We are not stepping. |
1519 } else { | 1532 } else { |
1520 JavaScriptFrameIterator frame_it(isolate_, break_frame_id()); | 1533 JavaScriptFrameIterator frame_it(isolate_, break_frame_id()); |
1521 // If our frame is a top frame and we are stepping, we can do step-in | 1534 // If our frame is a top frame and we are stepping, we can do step-in |
1522 // at this place. | 1535 // at this place. |
1523 if (frame_it.frame()->id() != frame_id) continue; | 1536 if (frame_it.frame()->id() != frame_id) continue; |
1524 } | 1537 } |
(...skipping 923 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2448 } | 2461 } |
2449 | 2462 |
2450 | 2463 |
2451 void LockingCommandMessageQueue::Clear() { | 2464 void LockingCommandMessageQueue::Clear() { |
2452 base::LockGuard<base::Mutex> lock_guard(&mutex_); | 2465 base::LockGuard<base::Mutex> lock_guard(&mutex_); |
2453 queue_.Clear(); | 2466 queue_.Clear(); |
2454 } | 2467 } |
2455 | 2468 |
2456 } // namespace internal | 2469 } // namespace internal |
2457 } // namespace v8 | 2470 } // namespace v8 |
OLD | NEW |