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 BreakLocation::BreakLocation(Handle<DebugInfo> debug_info, RelocInfo* rinfo, | 61 BreakLocation::BreakLocation(Handle<DebugInfo> debug_info, DebugBreakType type, |
62 int position, int statement_position) | 62 int code_offset, int position, |
| 63 int statement_position) |
63 : debug_info_(debug_info), | 64 : debug_info_(debug_info), |
64 code_offset_(static_cast<int>(rinfo->pc() - debug_info->code()->entry())), | 65 code_offset_(code_offset), |
65 rmode_(rinfo->rmode()), | 66 type_(type), |
66 data_(rinfo->data()), | |
67 position_(position), | 67 position_(position), |
68 statement_position_(statement_position) {} | 68 statement_position_(statement_position) {} |
69 | 69 |
| 70 BreakLocation::Iterator* BreakLocation::GetIterator( |
| 71 Handle<DebugInfo> debug_info, BreakLocatorType type) { |
| 72 if (debug_info->shared()->HasBytecodeArray()) { |
| 73 UNIMPLEMENTED(); |
| 74 return nullptr; |
| 75 } |
| 76 return new CodeIterator(debug_info, type); |
| 77 } |
| 78 |
70 BreakLocation::Iterator::Iterator(Handle<DebugInfo> debug_info, | 79 BreakLocation::Iterator::Iterator(Handle<DebugInfo> debug_info, |
71 BreakLocatorType type) | 80 BreakLocatorType type) |
72 : debug_info_(debug_info), | 81 : debug_info_(debug_info), |
73 reloc_iterator_(debug_info->code(), GetModeMask(type)), | |
74 break_index_(-1), | 82 break_index_(-1), |
75 position_(1), | 83 position_(1), |
76 statement_position_(1) { | 84 statement_position_(1) { |
| 85 } |
| 86 |
| 87 BreakLocation::CodeIterator::CodeIterator(Handle<DebugInfo> debug_info, |
| 88 BreakLocatorType type) |
| 89 : Iterator(debug_info, type), |
| 90 reloc_iterator_(debug_info->abstract_code()->GetCode(), |
| 91 GetModeMask(type)) { |
77 if (!Done()) Next(); | 92 if (!Done()) Next(); |
78 } | 93 } |
79 | 94 |
80 | 95 int BreakLocation::CodeIterator::GetModeMask(BreakLocatorType type) { |
81 int BreakLocation::Iterator::GetModeMask(BreakLocatorType type) { | |
82 int mask = 0; | 96 int mask = 0; |
83 mask |= RelocInfo::ModeMask(RelocInfo::POSITION); | 97 mask |= RelocInfo::ModeMask(RelocInfo::POSITION); |
84 mask |= RelocInfo::ModeMask(RelocInfo::STATEMENT_POSITION); | 98 mask |= RelocInfo::ModeMask(RelocInfo::STATEMENT_POSITION); |
85 mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_RETURN); | 99 mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_RETURN); |
86 mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_CALL); | 100 mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_CALL); |
87 if (type == ALL_BREAK_LOCATIONS) { | 101 if (type == ALL_BREAK_LOCATIONS) { |
88 mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_POSITION); | 102 mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_POSITION); |
89 mask |= RelocInfo::ModeMask(RelocInfo::DEBUGGER_STATEMENT); | 103 mask |= RelocInfo::ModeMask(RelocInfo::DEBUGGER_STATEMENT); |
90 } | 104 } |
91 return mask; | 105 return mask; |
92 } | 106 } |
93 | 107 |
94 | 108 void BreakLocation::CodeIterator::Next() { |
95 void BreakLocation::Iterator::Next() { | |
96 DisallowHeapAllocation no_gc; | 109 DisallowHeapAllocation no_gc; |
97 DCHECK(!Done()); | 110 DCHECK(!Done()); |
98 | 111 |
99 // Iterate through reloc info for code and original code stopping at each | 112 // Iterate through reloc info for code and original code stopping at each |
100 // breakable code target. | 113 // breakable code target. |
101 bool first = break_index_ == -1; | 114 bool first = break_index_ == -1; |
102 while (!Done()) { | 115 while (!Done()) { |
103 if (!first) reloc_iterator_.next(); | 116 if (!first) reloc_iterator_.next(); |
104 first = false; | 117 first = false; |
105 if (Done()) return; | 118 if (Done()) return; |
(...skipping 26 matching lines...) Expand all Loading... |
132 position_ = 0; | 145 position_ = 0; |
133 } | 146 } |
134 statement_position_ = position_; | 147 statement_position_ = position_; |
135 } | 148 } |
136 | 149 |
137 break; | 150 break; |
138 } | 151 } |
139 break_index_++; | 152 break_index_++; |
140 } | 153 } |
141 | 154 |
| 155 BreakLocation BreakLocation::CodeIterator::GetBreakLocation() { |
| 156 DebugBreakType type; |
| 157 if (RelocInfo::IsDebugBreakSlotAtReturn(rmode())) { |
| 158 type = DEBUG_BREAK_SLOT_AT_RETURN; |
| 159 } else if (RelocInfo::IsDebugBreakSlotAtCall(rmode())) { |
| 160 type = DEBUG_BREAK_SLOT_AT_CALL; |
| 161 } else if (RelocInfo::IsDebuggerStatement(rmode())) { |
| 162 type = DEBUGGER_STATEMENT; |
| 163 } else if (RelocInfo::IsDebugBreakSlot(rmode())) { |
| 164 type = DEBUG_BREAK_SLOT; |
| 165 } else { |
| 166 type = NOT_DEBUG_BREAK; |
| 167 } |
| 168 return BreakLocation(debug_info_, type, code_offset(), position(), |
| 169 statement_position()); |
| 170 } |
142 | 171 |
143 // Find the break point at the supplied address, or the closest one before | 172 // Find the break point at the supplied address, or the closest one before |
144 // the address. | 173 // the address. |
145 BreakLocation BreakLocation::FromCodeOffset(Handle<DebugInfo> debug_info, | 174 BreakLocation BreakLocation::FromCodeOffset(Handle<DebugInfo> debug_info, |
146 int offset) { | 175 int offset) { |
147 Iterator it(debug_info, ALL_BREAK_LOCATIONS); | 176 base::SmartPointer<Iterator> it(GetIterator(debug_info)); |
148 it.SkipTo(BreakIndexFromCodeOffset(debug_info, offset)); | 177 it->SkipTo(BreakIndexFromCodeOffset(debug_info, offset)); |
149 return it.GetBreakLocation(); | 178 return it->GetBreakLocation(); |
150 } | 179 } |
151 | 180 |
152 // Move GetFirstFrameSummary Definition to here as FromFrame use it. | 181 // Move GetFirstFrameSummary Definition to here as FromFrame use it. |
153 FrameSummary GetFirstFrameSummary(JavaScriptFrame* frame) { | 182 FrameSummary GetFirstFrameSummary(JavaScriptFrame* frame) { |
154 List<FrameSummary> frames(FLAG_max_inlining_levels + 1); | 183 List<FrameSummary> frames(FLAG_max_inlining_levels + 1); |
155 frame->Summarize(&frames); | 184 frame->Summarize(&frames); |
156 return frames.first(); | 185 return frames.first(); |
157 } | 186 } |
158 | 187 |
159 BreakLocation BreakLocation::FromFrame(Handle<DebugInfo> debug_info, | 188 BreakLocation BreakLocation::FromFrame(Handle<DebugInfo> debug_info, |
160 JavaScriptFrame* frame) { | 189 JavaScriptFrame* frame) { |
161 // Code offset to the instruction after the current one, possibly a break | 190 // Code offset to the instruction after the current one, possibly a break |
162 // location as well. So the "- 1" to exclude it from the search. | 191 // location as well. So the "- 1" to exclude it from the search. |
163 // Get code offset from the unoptimized code. | 192 // Get code offset from the unoptimized code. |
164 FrameSummary summary = GetFirstFrameSummary(frame); | 193 FrameSummary summary = GetFirstFrameSummary(frame); |
165 return FromCodeOffset(debug_info, summary.code_offset() - 1); | 194 return FromCodeOffset(debug_info, summary.code_offset() - 1); |
166 } | 195 } |
167 | 196 |
168 // Find the break point at the supplied address, or the closest one before | 197 // Find the break point at the supplied address, or the closest one before |
169 // the address. | 198 // the address. |
170 void BreakLocation::FromCodeOffsetSameStatement( | 199 void BreakLocation::FromCodeOffsetSameStatement( |
171 Handle<DebugInfo> debug_info, int offset, List<BreakLocation>* result_out) { | 200 Handle<DebugInfo> debug_info, int offset, List<BreakLocation>* result_out) { |
172 int break_index = BreakIndexFromCodeOffset(debug_info, offset); | 201 int break_index = BreakIndexFromCodeOffset(debug_info, offset); |
173 Iterator it(debug_info, ALL_BREAK_LOCATIONS); | 202 base::SmartPointer<Iterator> it(GetIterator(debug_info)); |
174 it.SkipTo(break_index); | 203 it->SkipTo(break_index); |
175 int statement_position = it.statement_position(); | 204 int statement_position = it->statement_position(); |
176 while (!it.Done() && it.statement_position() == statement_position) { | 205 while (!it->Done() && it->statement_position() == statement_position) { |
177 result_out->Add(it.GetBreakLocation()); | 206 result_out->Add(it->GetBreakLocation()); |
178 it.Next(); | 207 it->Next(); |
179 } | 208 } |
180 } | 209 } |
181 | 210 |
182 | 211 |
183 void BreakLocation::AllForStatementPosition(Handle<DebugInfo> debug_info, | 212 void BreakLocation::AllForStatementPosition(Handle<DebugInfo> debug_info, |
184 int statement_position, | 213 int statement_position, |
185 List<BreakLocation>* result_out) { | 214 List<BreakLocation>* result_out) { |
186 for (Iterator it(debug_info, ALL_BREAK_LOCATIONS); !it.Done(); it.Next()) { | 215 for (base::SmartPointer<Iterator> it(GetIterator(debug_info)); !it->Done(); |
187 if (it.statement_position() == statement_position) { | 216 it->Next()) { |
188 result_out->Add(it.GetBreakLocation()); | 217 if (it->statement_position() == statement_position) { |
| 218 result_out->Add(it->GetBreakLocation()); |
189 } | 219 } |
190 } | 220 } |
191 } | 221 } |
192 | 222 |
193 int BreakLocation::BreakIndexFromCodeOffset(Handle<DebugInfo> debug_info, | 223 int BreakLocation::BreakIndexFromCodeOffset(Handle<DebugInfo> debug_info, |
194 int offset) { | 224 int offset) { |
195 // Run through all break points to locate the one closest to the address. | 225 // Run through all break points to locate the one closest to the address. |
196 int closest_break = 0; | 226 int closest_break = 0; |
197 int distance = kMaxInt; | 227 int distance = kMaxInt; |
198 Code* code = debug_info->code(); | 228 DCHECK(0 <= offset && offset < debug_info->abstract_code()->Size()); |
199 DCHECK(0 <= offset && offset < code->instruction_size()); | 229 for (base::SmartPointer<Iterator> it(GetIterator(debug_info)); !it->Done(); |
200 Address pc = code->instruction_start() + offset; | 230 it->Next()) { |
201 for (Iterator it(debug_info, ALL_BREAK_LOCATIONS); !it.Done(); it.Next()) { | |
202 // Check if this break point is closer that what was previously found. | 231 // Check if this break point is closer that what was previously found. |
203 if (it.pc() <= pc && pc - it.pc() < distance) { | 232 if (it->code_offset() <= offset && offset - it->code_offset() < distance) { |
204 closest_break = it.break_index(); | 233 closest_break = it->break_index(); |
205 distance = static_cast<int>(pc - it.pc()); | 234 distance = offset - it->code_offset(); |
206 // Check whether we can't get any closer. | 235 // Check whether we can't get any closer. |
207 if (distance == 0) break; | 236 if (distance == 0) break; |
208 } | 237 } |
209 } | 238 } |
210 return closest_break; | 239 return closest_break; |
211 } | 240 } |
212 | 241 |
213 | 242 |
214 BreakLocation BreakLocation::FromPosition(Handle<DebugInfo> debug_info, | 243 BreakLocation BreakLocation::FromPosition(Handle<DebugInfo> debug_info, |
215 int position, | 244 int position, |
216 BreakPositionAlignment alignment) { | 245 BreakPositionAlignment alignment) { |
217 // Run through all break points to locate the one closest to the source | 246 // Run through all break points to locate the one closest to the source |
218 // position. | 247 // position. |
219 int closest_break = 0; | |
220 int distance = kMaxInt; | 248 int distance = kMaxInt; |
221 | 249 base::SmartPointer<Iterator> it(GetIterator(debug_info)); |
222 for (Iterator it(debug_info, ALL_BREAK_LOCATIONS); !it.Done(); it.Next()) { | 250 BreakLocation closest_break = it->GetBreakLocation(); |
| 251 while (!it->Done()) { |
223 int next_position; | 252 int next_position; |
224 if (alignment == STATEMENT_ALIGNED) { | 253 if (alignment == STATEMENT_ALIGNED) { |
225 next_position = it.statement_position(); | 254 next_position = it->statement_position(); |
226 } else { | 255 } else { |
227 DCHECK(alignment == BREAK_POSITION_ALIGNED); | 256 DCHECK(alignment == BREAK_POSITION_ALIGNED); |
228 next_position = it.position(); | 257 next_position = it->position(); |
229 } | 258 } |
230 if (position <= next_position && next_position - position < distance) { | 259 if (position <= next_position && next_position - position < distance) { |
231 closest_break = it.break_index(); | 260 closest_break = it->GetBreakLocation(); |
232 distance = next_position - position; | 261 distance = next_position - position; |
233 // Check whether we can't get any closer. | 262 // Check whether we can't get any closer. |
234 if (distance == 0) break; | 263 if (distance == 0) break; |
235 } | 264 } |
| 265 it->Next(); |
236 } | 266 } |
237 | 267 return closest_break; |
238 Iterator it(debug_info, ALL_BREAK_LOCATIONS); | |
239 it.SkipTo(closest_break); | |
240 return it.GetBreakLocation(); | |
241 } | 268 } |
242 | 269 |
243 | 270 |
244 void BreakLocation::SetBreakPoint(Handle<Object> break_point_object) { | 271 void BreakLocation::SetBreakPoint(Handle<Object> break_point_object) { |
245 // If there is not already a real break point here patch code with debug | 272 // If there is not already a real break point here patch code with debug |
246 // break. | 273 // break. |
247 if (!HasBreakPoint()) SetDebugBreak(); | 274 if (!HasBreakPoint()) SetDebugBreak(); |
248 DCHECK(IsDebugBreak() || IsDebuggerStatement()); | 275 DCHECK(IsDebugBreak() || IsDebuggerStatement()); |
249 // Set the break point information. | 276 // Set the break point information. |
250 DebugInfo::SetBreakPoint(debug_info_, code_offset_, position_, | 277 DebugInfo::SetBreakPoint(debug_info_, code_offset_, position_, |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
298 // Debugger statement always calls debugger. No need to modify it. | 325 // Debugger statement always calls debugger. No need to modify it. |
299 if (IsDebuggerStatement()) return; | 326 if (IsDebuggerStatement()) return; |
300 | 327 |
301 // If there is already a break point here just return. This might happen if | 328 // If there is already a break point here just return. This might happen if |
302 // the same code is flooded with break points twice. Flooding the same | 329 // the same code is flooded with break points twice. Flooding the same |
303 // function twice might happen when stepping in a function with an exception | 330 // function twice might happen when stepping in a function with an exception |
304 // handler as the handler and the function is the same. | 331 // handler as the handler and the function is the same. |
305 if (IsDebugBreak()) return; | 332 if (IsDebugBreak()) return; |
306 | 333 |
307 DCHECK(IsDebugBreakSlot()); | 334 DCHECK(IsDebugBreakSlot()); |
308 Isolate* isolate = debug_info_->GetIsolate(); | 335 if (abstract_code()->IsCode()) { |
309 Builtins* builtins = isolate->builtins(); | 336 Code* code = abstract_code()->GetCode(); |
310 Handle<Code> target = | 337 DCHECK(code->kind() == Code::FUNCTION); |
311 IsReturn() ? builtins->Return_DebugBreak() : builtins->Slot_DebugBreak(); | 338 Builtins* builtins = isolate()->builtins(); |
312 DebugCodegen::PatchDebugBreakSlot(isolate, pc(), target); | 339 Handle<Code> target = IsReturn() ? builtins->Return_DebugBreak() |
313 DCHECK(IsDebugBreak()); | 340 : builtins->Slot_DebugBreak(); |
| 341 Address pc = code->instruction_start() + code_offset(); |
| 342 DebugCodegen::PatchDebugBreakSlot(isolate(), pc, target); |
| 343 DCHECK(IsDebugBreak()); |
| 344 } else { |
| 345 UNIMPLEMENTED(); |
| 346 } |
314 } | 347 } |
315 | 348 |
316 | 349 |
317 void BreakLocation::ClearDebugBreak() { | 350 void BreakLocation::ClearDebugBreak() { |
318 // Debugger statement always calls debugger. No need to modify it. | 351 // Debugger statement always calls debugger. No need to modify it. |
319 if (IsDebuggerStatement()) return; | 352 if (IsDebuggerStatement()) return; |
320 | 353 |
321 DCHECK(IsDebugBreakSlot()); | 354 DCHECK(IsDebugBreakSlot()); |
322 DebugCodegen::ClearDebugBreakSlot(debug_info_->GetIsolate(), pc()); | 355 if (abstract_code()->IsCode()) { |
323 DCHECK(!IsDebugBreak()); | 356 Code* code = abstract_code()->GetCode(); |
| 357 DCHECK(code->kind() == Code::FUNCTION); |
| 358 Address pc = code->instruction_start() + code_offset(); |
| 359 DebugCodegen::ClearDebugBreakSlot(isolate(), pc); |
| 360 DCHECK(!IsDebugBreak()); |
| 361 } else { |
| 362 UNIMPLEMENTED(); |
| 363 } |
324 } | 364 } |
325 | 365 |
326 | 366 |
327 bool BreakLocation::IsDebugBreak() const { | 367 bool BreakLocation::IsDebugBreak() const { |
328 if (IsDebuggerStatement()) return false; | 368 if (IsDebuggerStatement()) return false; |
329 DCHECK(IsDebugBreakSlot()); | 369 DCHECK(IsDebugBreakSlot()); |
330 return rinfo().IsPatchedDebugBreakSlotSequence(); | 370 if (abstract_code()->IsCode()) { |
| 371 Code* code = abstract_code()->GetCode(); |
| 372 DCHECK(code->kind() == Code::FUNCTION); |
| 373 Address pc = code->instruction_start() + code_offset(); |
| 374 return DebugCodegen::DebugBreakSlotIsPatched(pc); |
| 375 } else { |
| 376 UNIMPLEMENTED(); |
| 377 return false; |
| 378 } |
331 } | 379 } |
332 | 380 |
333 | 381 |
334 Handle<Object> BreakLocation::BreakPointObjects() const { | 382 Handle<Object> BreakLocation::BreakPointObjects() const { |
335 return debug_info_->GetBreakPointObjects(code_offset_); | 383 return debug_info_->GetBreakPointObjects(code_offset_); |
336 } | 384 } |
337 | 385 |
338 | |
339 void DebugFeatureTracker::Track(DebugFeatureTracker::Feature feature) { | 386 void DebugFeatureTracker::Track(DebugFeatureTracker::Feature feature) { |
340 uint32_t mask = 1 << feature; | 387 uint32_t mask = 1 << feature; |
341 // Only count one sample per feature and isolate. | 388 // Only count one sample per feature and isolate. |
342 if (bitfield_ & mask) return; | 389 if (bitfield_ & mask) return; |
343 isolate_->counters()->debug_feature_usage()->AddSample(feature); | 390 isolate_->counters()->debug_feature_usage()->AddSample(feature); |
344 bitfield_ |= mask; | 391 bitfield_ |= mask; |
345 } | 392 } |
346 | 393 |
347 | 394 |
348 // Threading support. | 395 // Threading support. |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
493 return; | 540 return; |
494 case StepOut: | 541 case StepOut: |
495 // Step out has not reached the target frame yet. | 542 // Step out has not reached the target frame yet. |
496 if (current_fp < target_fp) return; | 543 if (current_fp < target_fp) return; |
497 break; | 544 break; |
498 case StepNext: | 545 case StepNext: |
499 // Step next should not break in a deeper frame. | 546 // Step next should not break in a deeper frame. |
500 if (current_fp < target_fp) return; | 547 if (current_fp < target_fp) return; |
501 // Fall through. | 548 // Fall through. |
502 case StepIn: { | 549 case StepIn: { |
503 int offset = | 550 FrameSummary summary = GetFirstFrameSummary(frame); |
504 static_cast<int>(frame->pc() - location.code()->instruction_start()); | 551 int offset = summary.code_offset(); |
505 step_break = location.IsReturn() || (current_fp != last_fp) || | 552 step_break = location.IsReturn() || (current_fp != last_fp) || |
506 (thread_local_.last_statement_position_ != | 553 (thread_local_.last_statement_position_ != |
507 location.code()->SourceStatementPosition(offset)); | 554 location.abstract_code()->SourceStatementPosition(offset)); |
508 break; | 555 break; |
509 } | 556 } |
510 case StepFrame: | 557 case StepFrame: |
511 step_break = current_fp != last_fp; | 558 step_break = current_fp != last_fp; |
512 break; | 559 break; |
513 } | 560 } |
514 | 561 |
515 // Clear all current stepping setup. | 562 // Clear all current stepping setup. |
516 ClearStepping(); | 563 ClearStepping(); |
517 | 564 |
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
737 } | 784 } |
738 } | 785 } |
739 | 786 |
740 | 787 |
741 // Clear out all the debug break code. This is ONLY supposed to be used when | 788 // Clear out all the debug break code. This is ONLY supposed to be used when |
742 // shutting down the debugger as it will leave the break point information in | 789 // shutting down the debugger as it will leave the break point information in |
743 // DebugInfo even though the code is patched back to the non break point state. | 790 // DebugInfo even though the code is patched back to the non break point state. |
744 void Debug::ClearAllBreakPoints() { | 791 void Debug::ClearAllBreakPoints() { |
745 for (DebugInfoListNode* node = debug_info_list_; node != NULL; | 792 for (DebugInfoListNode* node = debug_info_list_; node != NULL; |
746 node = node->next()) { | 793 node = node->next()) { |
747 for (BreakLocation::Iterator it(node->debug_info(), ALL_BREAK_LOCATIONS); | 794 for (base::SmartPointer<BreakLocation::Iterator> it( |
748 !it.Done(); it.Next()) { | 795 BreakLocation::GetIterator(node->debug_info())); |
749 it.GetBreakLocation().ClearDebugBreak(); | 796 !it->Done(); it->Next()) { |
| 797 it->GetBreakLocation().ClearDebugBreak(); |
750 } | 798 } |
751 } | 799 } |
752 // Remove all debug info. | 800 // Remove all debug info. |
753 while (debug_info_list_ != NULL) { | 801 while (debug_info_list_ != NULL) { |
754 RemoveDebugInfoAndClearFromShared(debug_info_list_->debug_info()); | 802 RemoveDebugInfoAndClearFromShared(debug_info_list_->debug_info()); |
755 } | 803 } |
756 } | 804 } |
757 | 805 |
758 | 806 |
759 void Debug::FloodWithOneShot(Handle<JSFunction> function, | 807 void Debug::FloodWithOneShot(Handle<JSFunction> function, |
(...skipping 10 matching lines...) Expand all Loading... |
770 } | 818 } |
771 // Make sure the function is compiled and has set up the debug info. | 819 // Make sure the function is compiled and has set up the debug info. |
772 Handle<SharedFunctionInfo> shared(function->shared()); | 820 Handle<SharedFunctionInfo> shared(function->shared()); |
773 if (!EnsureDebugInfo(shared, function)) { | 821 if (!EnsureDebugInfo(shared, function)) { |
774 // Return if we failed to retrieve the debug info. | 822 // Return if we failed to retrieve the debug info. |
775 return; | 823 return; |
776 } | 824 } |
777 | 825 |
778 // Flood the function with break points. | 826 // Flood the function with break points. |
779 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); | 827 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); |
780 for (BreakLocation::Iterator it(debug_info, type); !it.Done(); it.Next()) { | 828 for (base::SmartPointer<BreakLocation::Iterator> it( |
781 it.GetBreakLocation().SetOneShot(); | 829 BreakLocation::GetIterator(debug_info, type)); |
| 830 !it->Done(); it->Next()) { |
| 831 it->GetBreakLocation().SetOneShot(); |
782 } | 832 } |
783 } | 833 } |
784 | 834 |
785 | 835 |
786 void Debug::ChangeBreakOnException(ExceptionBreakType type, bool enable) { | 836 void Debug::ChangeBreakOnException(ExceptionBreakType type, bool enable) { |
787 if (type == BreakUncaughtException) { | 837 if (type == BreakUncaughtException) { |
788 break_on_uncaught_exception_ = enable; | 838 break_on_uncaught_exception_ = enable; |
789 } else { | 839 } else { |
790 break_on_exception_ = enable; | 840 break_on_exception_ = enable; |
791 } | 841 } |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
891 | 941 |
892 // PC points to the instruction after the current one, possibly a break | 942 // PC points to the instruction after the current one, possibly a break |
893 // location as well. So the "- 1" to exclude it from the search. | 943 // location as well. So the "- 1" to exclude it from the search. |
894 BreakLocation location = | 944 BreakLocation location = |
895 BreakLocation::FromCodeOffset(debug_info, summary.code_offset() - 1); | 945 BreakLocation::FromCodeOffset(debug_info, summary.code_offset() - 1); |
896 | 946 |
897 // At a return statement we will step out either way. | 947 // At a return statement we will step out either way. |
898 if (location.IsReturn()) step_action = StepOut; | 948 if (location.IsReturn()) step_action = StepOut; |
899 | 949 |
900 thread_local_.last_statement_position_ = | 950 thread_local_.last_statement_position_ = |
901 debug_info->code()->SourceStatementPosition(summary.code_offset()); | 951 debug_info->abstract_code()->SourceStatementPosition( |
| 952 summary.code_offset()); |
902 thread_local_.last_fp_ = frame->UnpaddedFP(); | 953 thread_local_.last_fp_ = frame->UnpaddedFP(); |
903 | 954 |
904 switch (step_action) { | 955 switch (step_action) { |
905 case StepNone: | 956 case StepNone: |
906 UNREACHABLE(); | 957 UNREACHABLE(); |
907 break; | 958 break; |
908 case StepOut: | 959 case StepOut: |
909 // Advance to caller frame. | 960 // Advance to caller frame. |
910 frames_it.Advance(); | 961 frames_it.Advance(); |
911 // Skip native and extension functions on the stack. | 962 // Skip native and extension functions on the stack. |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
998 | 1049 |
999 // Clears all the one-shot break points that are currently set. Normally this | 1050 // Clears all the one-shot break points that are currently set. Normally this |
1000 // function is called each time a break point is hit as one shot break points | 1051 // function is called each time a break point is hit as one shot break points |
1001 // are used to support stepping. | 1052 // are used to support stepping. |
1002 void Debug::ClearOneShot() { | 1053 void Debug::ClearOneShot() { |
1003 // The current implementation just runs through all the breakpoints. When the | 1054 // The current implementation just runs through all the breakpoints. When the |
1004 // last break point for a function is removed that function is automatically | 1055 // last break point for a function is removed that function is automatically |
1005 // removed from the list. | 1056 // removed from the list. |
1006 for (DebugInfoListNode* node = debug_info_list_; node != NULL; | 1057 for (DebugInfoListNode* node = debug_info_list_; node != NULL; |
1007 node = node->next()) { | 1058 node = node->next()) { |
1008 for (BreakLocation::Iterator it(node->debug_info(), ALL_BREAK_LOCATIONS); | 1059 for (base::SmartPointer<BreakLocation::Iterator> it( |
1009 !it.Done(); it.Next()) { | 1060 BreakLocation::GetIterator(node->debug_info())); |
1010 it.GetBreakLocation().ClearOneShot(); | 1061 !it->Done(); it->Next()) { |
| 1062 it->GetBreakLocation().ClearOneShot(); |
1011 } | 1063 } |
1012 } | 1064 } |
1013 } | 1065 } |
1014 | 1066 |
1015 | 1067 |
1016 void Debug::EnableStepIn() { | 1068 void Debug::EnableStepIn() { |
1017 STATIC_ASSERT(StepFrame > StepIn); | 1069 STATIC_ASSERT(StepFrame > StepIn); |
1018 thread_local_.step_in_enabled_ = (last_step_action() >= StepIn); | 1070 thread_local_.step_in_enabled_ = (last_step_action() >= StepIn); |
1019 } | 1071 } |
1020 | 1072 |
(...skipping 410 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1431 | 1483 |
1432 bool Debug::IsBreakAtReturn(JavaScriptFrame* frame) { | 1484 bool Debug::IsBreakAtReturn(JavaScriptFrame* frame) { |
1433 HandleScope scope(isolate_); | 1485 HandleScope scope(isolate_); |
1434 | 1486 |
1435 // Get the executing function in which the debug break occurred. | 1487 // Get the executing function in which the debug break occurred. |
1436 Handle<JSFunction> function(JSFunction::cast(frame->function())); | 1488 Handle<JSFunction> function(JSFunction::cast(frame->function())); |
1437 Handle<SharedFunctionInfo> shared(function->shared()); | 1489 Handle<SharedFunctionInfo> shared(function->shared()); |
1438 | 1490 |
1439 // With no debug info there are no break points, so we can't be at a return. | 1491 // With no debug info there are no break points, so we can't be at a return. |
1440 if (!shared->HasDebugInfo()) return false; | 1492 if (!shared->HasDebugInfo()) return false; |
| 1493 |
| 1494 DCHECK(!frame->is_optimized()); |
| 1495 FrameSummary summary = GetFirstFrameSummary(frame); |
| 1496 |
1441 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); | 1497 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); |
1442 Handle<Code> code(debug_info->code()); | 1498 BreakLocation location = |
1443 #ifdef DEBUG | 1499 BreakLocation::FromCodeOffset(debug_info, summary.code_offset()); |
1444 // Get the code which is actually executing. | 1500 return location.IsReturn(); |
1445 Handle<Code> frame_code(frame->LookupCode()); | |
1446 DCHECK(frame_code.is_identical_to(code)); | |
1447 #endif | |
1448 | |
1449 // Find the reloc info matching the start of the debug break slot. | |
1450 Address slot_pc = frame->pc() - Assembler::kDebugBreakSlotLength; | |
1451 int mask = RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_RETURN); | |
1452 for (RelocIterator it(*code, mask); !it.done(); it.next()) { | |
1453 if (it.rinfo()->pc() == slot_pc) return true; | |
1454 } | |
1455 return false; | |
1456 } | 1501 } |
1457 | 1502 |
1458 | 1503 |
1459 void Debug::FramesHaveBeenDropped(StackFrame::Id new_break_frame_id, | 1504 void Debug::FramesHaveBeenDropped(StackFrame::Id new_break_frame_id, |
1460 LiveEdit::FrameDropMode mode) { | 1505 LiveEdit::FrameDropMode mode) { |
1461 if (mode != LiveEdit::CURRENTLY_SET_MODE) { | 1506 if (mode != LiveEdit::CURRENTLY_SET_MODE) { |
1462 thread_local_.frame_drop_mode_ = mode; | 1507 thread_local_.frame_drop_mode_ = mode; |
1463 } | 1508 } |
1464 thread_local_.break_frame_id_ = new_break_frame_id; | 1509 thread_local_.break_frame_id_ = new_break_frame_id; |
1465 } | 1510 } |
(...skipping 994 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2460 } | 2505 } |
2461 | 2506 |
2462 | 2507 |
2463 void LockingCommandMessageQueue::Clear() { | 2508 void LockingCommandMessageQueue::Clear() { |
2464 base::LockGuard<base::Mutex> lock_guard(&mutex_); | 2509 base::LockGuard<base::Mutex> lock_guard(&mutex_); |
2465 queue_.Clear(); | 2510 queue_.Clear(); |
2466 } | 2511 } |
2467 | 2512 |
2468 } // namespace internal | 2513 } // namespace internal |
2469 } // namespace v8 | 2514 } // namespace v8 |
OLD | NEW |