| 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 |