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 |