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 14 matching lines...) Expand all Loading... |
25 #include "src/wasm/wasm-debug.h" | 25 #include "src/wasm/wasm-debug.h" |
26 #include "src/wasm/wasm-module.h" | 26 #include "src/wasm/wasm-module.h" |
27 | 27 |
28 #include "include/v8-debug.h" | 28 #include "include/v8-debug.h" |
29 | 29 |
30 namespace v8 { | 30 namespace v8 { |
31 namespace internal { | 31 namespace internal { |
32 | 32 |
33 namespace { | 33 namespace { |
34 | 34 |
35 inline int CallOffsetFromCodeOffset(int code_offset, bool is_interpreted) { | 35 inline int GetCodeOffset(StandardFrame* frame) { |
| 36 // Frame summary is top-down, i.e. caller before callee. |
| 37 // For whatever reason, javascript takes the lowest caller as the code offset |
| 38 // for the frame, where for wasm we need the highest one. |
| 39 return frame->is_java_script() ? FrameSummary::GetFirst(frame).code_offset() |
| 40 : FrameSummary::GetLast(frame).code_offset(); |
| 41 } |
| 42 |
| 43 inline int CallOffsetFromCodeOffset(int code_offset, StandardFrame* frame) { |
36 // Code offset points to the instruction after the call. Subtract 1 to | 44 // Code offset points to the instruction after the call. Subtract 1 to |
37 // exclude that instruction from the search. For bytecode, the code offset | 45 // exclude that instruction from the search. For interpreted frames, the code |
38 // still points to the call. | 46 // offset still points to the call. |
39 return is_interpreted ? code_offset : code_offset - 1; | 47 bool interpreted = frame->is_interpreted() || frame->is_wasm_interpreted(); |
| 48 return interpreted ? code_offset : code_offset - 1; |
| 49 } |
| 50 |
| 51 std::pair<Handle<JSObject>, int> GetWasmObjectAndFunctionIndexFromCode( |
| 52 Code* code) { |
| 53 FixedArray* deopt_data = code->deoptimization_data(); |
| 54 DCHECK_EQ(2, deopt_data->length()); |
| 55 Handle<JSObject> wasm(JSObject::cast(deopt_data->get(0))); |
| 56 int func_index = Smi::cast(deopt_data->get(1))->value(); |
| 57 return std::make_pair(wasm, func_index); |
40 } | 58 } |
41 | 59 |
42 } // namespace | 60 } // namespace |
43 | 61 |
44 Debug::Debug(Isolate* isolate) | 62 Debug::Debug(Isolate* isolate) |
45 : debug_context_(Handle<Context>()), | 63 : debug_context_(Handle<Context>()), |
46 event_listener_(Handle<Object>()), | 64 event_listener_(Handle<Object>()), |
47 event_listener_data_(Handle<Object>()), | 65 event_listener_data_(Handle<Object>()), |
48 message_handler_(NULL), | 66 message_handler_(NULL), |
49 command_received_(0), | 67 command_received_(0), |
(...skipping 28 matching lines...) Expand all Loading... |
78 : debug_info_(debug_info), | 96 : debug_info_(debug_info), |
79 code_offset_(code_offset), | 97 code_offset_(code_offset), |
80 type_(type), | 98 type_(type), |
81 position_(position), | 99 position_(position), |
82 statement_position_(statement_position) {} | 100 statement_position_(statement_position) {} |
83 | 101 |
84 BreakLocation::Iterator* BreakLocation::GetIterator( | 102 BreakLocation::Iterator* BreakLocation::GetIterator( |
85 Handle<DebugInfo> debug_info, BreakLocatorType type) { | 103 Handle<DebugInfo> debug_info, BreakLocatorType type) { |
86 if (debug_info->abstract_code()->IsBytecodeArray()) { | 104 if (debug_info->abstract_code()->IsBytecodeArray()) { |
87 return new BytecodeArrayIterator(debug_info, type); | 105 return new BytecodeArrayIterator(debug_info, type); |
| 106 } else if (debug_info->abstract_code()->GetCode()->kind() == |
| 107 Code::WASM_FUNCTION) { |
| 108 return new WasmBytecodeIterator(debug_info, type); |
88 } else { | 109 } else { |
89 return new CodeIterator(debug_info, type); | 110 return new CodeIterator(debug_info, type); |
90 } | 111 } |
91 } | 112 } |
92 | 113 |
93 BreakLocation::Iterator::Iterator(Handle<DebugInfo> debug_info) | 114 BreakLocation::Iterator::Iterator(Handle<DebugInfo> debug_info) |
94 : debug_info_(debug_info), | 115 : debug_info_(debug_info), |
95 break_index_(-1), | 116 break_index_(-1), |
96 position_(1), | 117 position_(1), |
97 statement_position_(1) {} | 118 statement_position_(1) {} |
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
257 } else { | 278 } else { |
258 return NOT_DEBUG_BREAK; | 279 return NOT_DEBUG_BREAK; |
259 } | 280 } |
260 } | 281 } |
261 | 282 |
262 BreakLocation BreakLocation::BytecodeArrayIterator::GetBreakLocation() { | 283 BreakLocation BreakLocation::BytecodeArrayIterator::GetBreakLocation() { |
263 return BreakLocation(debug_info_, GetDebugBreakType(), code_offset(), | 284 return BreakLocation(debug_info_, GetDebugBreakType(), code_offset(), |
264 position(), statement_position()); | 285 position(), statement_position()); |
265 } | 286 } |
266 | 287 |
| 288 namespace { |
| 289 |
| 290 wasm::WasmInstructionIterator GetWasmInsnIterator( |
| 291 Handle<DebugInfo> debug_info) { |
| 292 auto wasm_and_index = GetWasmObjectAndFunctionIndexFromCode( |
| 293 debug_info->abstract_code()->GetCode()); |
| 294 Handle<wasm::WasmDebugInfo> wasm_debug_info( |
| 295 wasm::GetDebugInfo(wasm_and_index.first)); |
| 296 return wasm::WasmDebugInfo::GetInstructionIterator(wasm_debug_info, |
| 297 wasm_and_index.second); |
| 298 } |
| 299 |
| 300 } // namespace |
| 301 |
| 302 BreakLocation::WasmBytecodeIterator::WasmBytecodeIterator( |
| 303 Handle<DebugInfo> debug_info, BreakLocatorType type) |
| 304 : Iterator(debug_info), |
| 305 wasm_insn_iterator(GetWasmInsnIterator(debug_info)), |
| 306 break_locator_type_(type) { |
| 307 // Get wasm object and function index from deopt data. |
| 308 Code* code = debug_info->abstract_code()->GetCode(); |
| 309 Handle<JSObject> wasm; |
| 310 std::tie(wasm, func_index) = GetWasmObjectAndFunctionIndexFromCode(code); |
| 311 wasm_debug_info = handle(wasm::GetDebugInfo(wasm)); |
| 312 Next(); |
| 313 } |
| 314 |
| 315 BreakLocation BreakLocation::WasmBytecodeIterator::GetBreakLocation() { |
| 316 DebugBreakType type; |
| 317 switch (wasm_debug_info->GetInstructionType(func_index, |
| 318 wasm_insn_iterator.pc_offset())) { |
| 319 case wasm::WasmDebugInfo::InstructionType::RETURN: |
| 320 type = DEBUG_BREAK_SLOT_AT_RETURN; |
| 321 break; |
| 322 case wasm::WasmDebugInfo::InstructionType::CALL: |
| 323 type = DEBUG_BREAK_SLOT_AT_CALL; |
| 324 break; |
| 325 default: |
| 326 type = DEBUG_BREAK_SLOT; |
| 327 break; |
| 328 } |
| 329 return BreakLocation(debug_info_, type, code_offset(), position(), |
| 330 statement_position()); |
| 331 } |
| 332 |
| 333 void BreakLocation::WasmBytecodeIterator::Next() { |
| 334 ++break_index_; |
| 335 for (bool first = break_index_ == 0; !Done(); first = false) { |
| 336 if (!first) wasm_insn_iterator.Next(); |
| 337 position_ = statement_position_ = wasm_insn_iterator.pc_offset(); |
| 338 if (break_locator_type_ == ALL_BREAK_LOCATIONS) break; |
| 339 DCHECK_EQ(BreakLocatorType::CALLS_AND_RETURNS, break_locator_type_); |
| 340 using InsnType = wasm::WasmDebugInfo::InstructionType; |
| 341 InsnType type = wasm_debug_info->GetInstructionType(func_index, position_); |
| 342 if (type == InsnType::RETURN || type == InsnType::CALL) break; |
| 343 } |
| 344 } |
| 345 |
267 // Find the break point at the supplied address, or the closest one before | 346 // Find the break point at the supplied address, or the closest one before |
268 // the address. | 347 // the address. |
269 BreakLocation BreakLocation::FromCodeOffset(Handle<DebugInfo> debug_info, | 348 BreakLocation BreakLocation::FromCodeOffset(Handle<DebugInfo> debug_info, |
270 int offset) { | 349 int offset) { |
271 base::SmartPointer<Iterator> it(GetIterator(debug_info)); | 350 base::SmartPointer<Iterator> it(GetIterator(debug_info)); |
272 it->SkipTo(BreakIndexFromCodeOffset(debug_info, offset)); | 351 it->SkipTo(BreakIndexFromCodeOffset(debug_info, offset)); |
273 return it->GetBreakLocation(); | 352 return it->GetBreakLocation(); |
274 } | 353 } |
275 | 354 |
276 BreakLocation BreakLocation::FromFrame(Handle<DebugInfo> debug_info, | 355 BreakLocation BreakLocation::FromFrame(StandardFrame* frame) { |
277 JavaScriptFrame* frame) { | 356 // Get the debug info (create it if it does not exist). |
278 int code_offset = FrameSummary::GetFirst(frame).code_offset(); | 357 Handle<DebugInfo> debug_info(DebugInfo::cast(frame->debug_info(true))); |
279 int call_offset = | 358 |
280 CallOffsetFromCodeOffset(code_offset, frame->is_interpreted()); | 359 int code_offset = GetCodeOffset(frame); |
| 360 int call_offset = CallOffsetFromCodeOffset(code_offset, frame); |
281 return FromCodeOffset(debug_info, call_offset); | 361 return FromCodeOffset(debug_info, call_offset); |
282 } | 362 } |
283 | 363 |
284 void BreakLocation::AllForStatementPosition(Handle<DebugInfo> debug_info, | 364 void BreakLocation::AllForStatementPosition(Handle<DebugInfo> debug_info, |
285 int statement_position, | 365 int statement_position, |
286 List<BreakLocation>* result_out) { | 366 List<BreakLocation>* result_out) { |
287 for (base::SmartPointer<Iterator> it(GetIterator(debug_info)); !it->Done(); | 367 for (base::SmartPointer<Iterator> it(GetIterator(debug_info)); !it->Done(); |
288 it->Next()) { | 368 it->Next()) { |
289 if (it->statement_position() == statement_position) { | 369 if (it->statement_position() == statement_position) { |
290 result_out->Add(it->GetBreakLocation()); | 370 result_out->Add(it->GetBreakLocation()); |
291 } | 371 } |
292 } | 372 } |
293 } | 373 } |
294 | 374 |
295 int BreakLocation::BreakIndexFromCodeOffset(Handle<DebugInfo> debug_info, | 375 int BreakLocation::BreakIndexFromCodeOffset(Handle<DebugInfo> debug_info, |
296 int offset) { | 376 int offset) { |
297 // Run through all break points to locate the one closest to the address. | 377 // Run through all break points to locate the one closest to the address. |
298 int closest_break = 0; | 378 int closest_break = 0; |
299 int distance = kMaxInt; | 379 int distance = kMaxInt; |
300 DCHECK(0 <= offset && offset < debug_info->abstract_code()->Size()); | 380 DCHECK_LE(0, offset); |
301 for (base::SmartPointer<Iterator> it(GetIterator(debug_info)); !it->Done(); | 381 for (base::SmartPointer<Iterator> it(GetIterator(debug_info)); !it->Done(); |
302 it->Next()) { | 382 it->Next()) { |
303 // Check if this break point is closer that what was previously found. | 383 // Check if this break point is closer that what was previously found. |
304 if (it->code_offset() <= offset && offset - it->code_offset() < distance) { | 384 if (it->code_offset() <= offset && offset - it->code_offset() < distance) { |
305 closest_break = it->break_index(); | 385 closest_break = it->break_index(); |
306 distance = offset - it->code_offset(); | 386 distance = offset - it->code_offset(); |
307 // Check whether we can't get any closer. | 387 // Check whether we can't get any closer. |
308 if (distance == 0) break; | 388 if (distance == 0) break; |
309 } | 389 } |
310 } | 390 } |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
399 | 479 |
400 // If there is already a break point here just return. This might happen if | 480 // If there is already a break point here just return. This might happen if |
401 // the same code is flooded with break points twice. Flooding the same | 481 // the same code is flooded with break points twice. Flooding the same |
402 // function twice might happen when stepping in a function with an exception | 482 // function twice might happen when stepping in a function with an exception |
403 // handler as the handler and the function is the same. | 483 // handler as the handler and the function is the same. |
404 if (IsDebugBreak()) return; | 484 if (IsDebugBreak()) return; |
405 | 485 |
406 DCHECK(IsDebugBreakSlot()); | 486 DCHECK(IsDebugBreakSlot()); |
407 if (abstract_code()->IsCode()) { | 487 if (abstract_code()->IsCode()) { |
408 Code* code = abstract_code()->GetCode(); | 488 Code* code = abstract_code()->GetCode(); |
409 DCHECK(code->kind() == Code::FUNCTION); | 489 if (code->kind() == Code::FUNCTION) { |
410 Builtins* builtins = isolate()->builtins(); | 490 Builtins* builtins = isolate()->builtins(); |
411 Handle<Code> target = IsReturn() ? builtins->Return_DebugBreak() | 491 Handle<Code> target = IsReturn() ? builtins->Return_DebugBreak() |
412 : builtins->Slot_DebugBreak(); | 492 : builtins->Slot_DebugBreak(); |
413 Address pc = code->instruction_start() + code_offset(); | 493 Address pc = code->instruction_start() + code_offset(); |
414 DebugCodegen::PatchDebugBreakSlot(isolate(), pc, target); | 494 DebugCodegen::PatchDebugBreakSlot(isolate(), pc, target); |
| 495 } else { |
| 496 DCHECK(code->kind() == Code::WASM_FUNCTION); |
| 497 // Get wasm object and function index from deopt data. |
| 498 Handle<JSObject> wasm; |
| 499 int func_index; |
| 500 std::tie(wasm, func_index) = GetWasmObjectAndFunctionIndexFromCode(code); |
| 501 Handle<wasm::WasmDebugInfo> debug_info(wasm::GetDebugInfo(wasm)); |
| 502 wasm::WasmDebugInfo::SetBreakpoint(debug_info, func_index, position()); |
| 503 } |
415 } else { | 504 } else { |
416 BytecodeArray* bytecode_array = abstract_code()->GetBytecodeArray(); | 505 BytecodeArray* bytecode_array = abstract_code()->GetBytecodeArray(); |
417 interpreter::Bytecode bytecode = | 506 interpreter::Bytecode bytecode = |
418 interpreter::Bytecodes::FromByte(bytecode_array->get(code_offset())); | 507 interpreter::Bytecodes::FromByte(bytecode_array->get(code_offset())); |
419 interpreter::Bytecode debugbreak = | 508 interpreter::Bytecode debugbreak = |
420 interpreter::Bytecodes::GetDebugBreak(bytecode); | 509 interpreter::Bytecodes::GetDebugBreak(bytecode); |
421 bytecode_array->set(code_offset(), | 510 bytecode_array->set(code_offset(), |
422 interpreter::Bytecodes::ToByte(debugbreak)); | 511 interpreter::Bytecodes::ToByte(debugbreak)); |
423 } | 512 } |
424 DCHECK(IsDebugBreak()); | 513 DCHECK(IsDebugBreak()); |
(...skipping 17 matching lines...) Expand all Loading... |
442 } | 531 } |
443 DCHECK(!IsDebugBreak()); | 532 DCHECK(!IsDebugBreak()); |
444 } | 533 } |
445 | 534 |
446 | 535 |
447 bool BreakLocation::IsDebugBreak() const { | 536 bool BreakLocation::IsDebugBreak() const { |
448 if (IsDebuggerStatement()) return false; | 537 if (IsDebuggerStatement()) return false; |
449 DCHECK(IsDebugBreakSlot()); | 538 DCHECK(IsDebugBreakSlot()); |
450 if (abstract_code()->IsCode()) { | 539 if (abstract_code()->IsCode()) { |
451 Code* code = abstract_code()->GetCode(); | 540 Code* code = abstract_code()->GetCode(); |
452 DCHECK(code->kind() == Code::FUNCTION); | 541 if (code->kind() == Code::FUNCTION) { |
453 Address pc = code->instruction_start() + code_offset(); | 542 Address pc = code->instruction_start() + code_offset(); |
454 return DebugCodegen::DebugBreakSlotIsPatched(pc); | 543 return DebugCodegen::DebugBreakSlotIsPatched(pc); |
| 544 } |
| 545 DCHECK(code->kind() == Code::WASM_FUNCTION); |
| 546 Handle<JSObject> wasm; |
| 547 int func_index; |
| 548 std::tie(wasm, func_index) = GetWasmObjectAndFunctionIndexFromCode(code); |
| 549 Handle<wasm::WasmDebugInfo> wasm_debug_info(wasm::GetDebugInfo(wasm)); |
| 550 return wasm_debug_info->HasBreakpoint(func_index, position()); |
455 } else { | 551 } else { |
456 BytecodeArray* bytecode_array = abstract_code()->GetBytecodeArray(); | 552 BytecodeArray* bytecode_array = abstract_code()->GetBytecodeArray(); |
457 interpreter::Bytecode bytecode = | 553 interpreter::Bytecode bytecode = |
458 interpreter::Bytecodes::FromByte(bytecode_array->get(code_offset())); | 554 interpreter::Bytecodes::FromByte(bytecode_array->get(code_offset())); |
459 return interpreter::Bytecodes::IsDebugBreak(bytecode); | 555 return interpreter::Bytecodes::IsDebugBreak(bytecode); |
460 } | 556 } |
461 } | 557 } |
462 | 558 |
463 | 559 |
464 Handle<Object> BreakLocation::BreakPointObjects() const { | 560 Handle<Object> BreakLocation::BreakPointObjects() const { |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
567 ClearStepping(); | 663 ClearStepping(); |
568 | 664 |
569 // Return debugger is not loaded. | 665 // Return debugger is not loaded. |
570 if (!is_loaded()) return; | 666 if (!is_loaded()) return; |
571 | 667 |
572 // Clear debugger context global handle. | 668 // Clear debugger context global handle. |
573 GlobalHandles::Destroy(Handle<Object>::cast(debug_context_).location()); | 669 GlobalHandles::Destroy(Handle<Object>::cast(debug_context_).location()); |
574 debug_context_ = Handle<Context>(); | 670 debug_context_ = Handle<Context>(); |
575 } | 671 } |
576 | 672 |
577 void Debug::Break(JavaScriptFrame* frame) { | 673 void Debug::Break(StandardFrame* frame) { |
578 HandleScope scope(isolate_); | 674 HandleScope scope(isolate_); |
579 | 675 |
580 // Initialize LiveEdit. | 676 // Initialize LiveEdit. |
581 LiveEdit::InitializeThreadLocal(this); | 677 LiveEdit::InitializeThreadLocal(this); |
582 | 678 |
583 // Just continue if breaks are disabled or debugger cannot be loaded. | 679 // Just continue if breaks are disabled or debugger cannot be loaded. |
584 if (break_disabled()) return; | 680 if (break_disabled()) return; |
585 | 681 |
586 // Enter the debugger. | 682 // Enter the debugger. |
587 DebugScope debug_scope(this); | 683 DebugScope debug_scope(this); |
588 if (debug_scope.failed()) return; | 684 if (debug_scope.failed()) return; |
589 | 685 |
590 // Postpone interrupt during breakpoint processing. | 686 // Postpone interrupt during breakpoint processing. |
591 PostponeInterruptsScope postpone(isolate_); | 687 PostponeInterruptsScope postpone(isolate_); |
592 | 688 |
593 // Get the debug info (create it if it does not exist). | |
594 Handle<JSFunction> function(frame->function()); | |
595 Handle<SharedFunctionInfo> shared(function->shared()); | |
596 if (!EnsureDebugInfo(shared, function)) { | |
597 // Return if we failed to retrieve the debug info. | |
598 return; | |
599 } | |
600 Handle<DebugInfo> debug_info(shared->GetDebugInfo(), isolate_); | |
601 | |
602 // Find the break location where execution has stopped. | 689 // Find the break location where execution has stopped. |
603 BreakLocation location = BreakLocation::FromFrame(debug_info, frame); | 690 BreakLocation location = BreakLocation::FromFrame(frame); |
604 | 691 |
605 // Find actual break points, if any, and trigger debug break event. | 692 // Find actual break points, if any, and trigger debug break event. |
606 Handle<Object> break_points_hit = CheckBreakPoints(&location); | 693 Handle<Object> break_points_hit = CheckBreakPoints(&location); |
607 if (!break_points_hit->IsUndefined(isolate_)) { | 694 if (!break_points_hit->IsUndefined(isolate_)) { |
608 // Clear all current stepping setup. | 695 // Clear all current stepping setup. |
609 ClearStepping(); | 696 ClearStepping(); |
610 // Notify the debug event listeners. | 697 // Notify the debug event listeners. |
611 OnDebugBreak(break_points_hit, false); | 698 OnDebugBreak(break_points_hit, false); |
612 return; | 699 return; |
613 } | 700 } |
(...skipping 13 matching lines...) Expand all Loading... |
627 if (current_fp < target_fp) return; | 714 if (current_fp < target_fp) return; |
628 step_break = true; | 715 step_break = true; |
629 break; | 716 break; |
630 case StepNext: | 717 case StepNext: |
631 // Step next should not break in a deeper frame. | 718 // Step next should not break in a deeper frame. |
632 if (current_fp < target_fp) return; | 719 if (current_fp < target_fp) return; |
633 // For step-next, a tail call is like a return and should break. | 720 // For step-next, a tail call is like a return and should break. |
634 step_break = location.IsTailCall(); | 721 step_break = location.IsTailCall(); |
635 // Fall through. | 722 // Fall through. |
636 case StepIn: { | 723 case StepIn: { |
637 FrameSummary summary = FrameSummary::GetFirst(frame); | 724 int offset = GetCodeOffset(frame); |
638 int offset = summary.code_offset(); | |
639 step_break = step_break || location.IsReturn() || | 725 step_break = step_break || location.IsReturn() || |
640 (current_fp != last_fp) || | 726 (current_fp != last_fp) || |
641 (thread_local_.last_statement_position_ != | 727 (thread_local_.last_statement_position_ != |
642 location.abstract_code()->SourceStatementPosition(offset)); | 728 location.abstract_code()->SourceStatementPosition(offset)); |
643 break; | 729 break; |
644 } | 730 } |
645 case StepFrame: | 731 case StepFrame: |
646 step_break = current_fp != last_fp; | 732 step_break = current_fp != last_fp; |
647 break; | 733 break; |
648 } | 734 } |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
706 // an exception event on exception at this location. | 792 // an exception event on exception at this location. |
707 Object* fun = frame->function(); | 793 Object* fun = frame->function(); |
708 if (!fun->IsJSFunction()) return false; | 794 if (!fun->IsJSFunction()) return false; |
709 JSFunction* function = JSFunction::cast(fun); | 795 JSFunction* function = JSFunction::cast(fun); |
710 if (!function->shared()->HasDebugInfo()) return false; | 796 if (!function->shared()->HasDebugInfo()) return false; |
711 HandleScope scope(isolate_); | 797 HandleScope scope(isolate_); |
712 Handle<DebugInfo> debug_info(function->shared()->GetDebugInfo()); | 798 Handle<DebugInfo> debug_info(function->shared()->GetDebugInfo()); |
713 // Enter the debugger. | 799 // Enter the debugger. |
714 DebugScope debug_scope(this); | 800 DebugScope debug_scope(this); |
715 if (debug_scope.failed()) return false; | 801 if (debug_scope.failed()) return false; |
716 BreakLocation current_position = BreakLocation::FromFrame(debug_info, frame); | 802 BreakLocation current_position = BreakLocation::FromFrame(frame); |
717 List<BreakLocation> break_locations; | 803 List<BreakLocation> break_locations; |
718 BreakLocation::AllForStatementPosition( | 804 BreakLocation::AllForStatementPosition( |
719 debug_info, current_position.statement_position(), &break_locations); | 805 debug_info, current_position.statement_position(), &break_locations); |
720 bool has_break_points_at_all = false; | 806 bool has_break_points_at_all = false; |
721 for (int i = 0; i < break_locations.length(); i++) { | 807 for (int i = 0; i < break_locations.length(); i++) { |
722 bool has_break_points; | 808 bool has_break_points; |
723 Handle<Object> check_result = | 809 Handle<Object> check_result = |
724 CheckBreakPoints(&break_locations[i], &has_break_points); | 810 CheckBreakPoints(&break_locations[i], &has_break_points); |
725 has_break_points_at_all |= has_break_points; | 811 has_break_points_at_all |= has_break_points; |
726 if (has_break_points && !check_result->IsUndefined(isolate_)) return false; | 812 if (has_break_points && !check_result->IsUndefined(isolate_)) return false; |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
792 | 878 |
793 // At least one active break point now. | 879 // At least one active break point now. |
794 return debug_info->GetBreakPointCount() > 0; | 880 return debug_info->GetBreakPointCount() > 0; |
795 } | 881 } |
796 | 882 |
797 | 883 |
798 bool Debug::SetBreakPointForScript(Handle<Script> script, | 884 bool Debug::SetBreakPointForScript(Handle<Script> script, |
799 Handle<Object> break_point_object, | 885 Handle<Object> break_point_object, |
800 int* source_position, | 886 int* source_position, |
801 BreakPositionAlignment alignment) { | 887 BreakPositionAlignment alignment) { |
802 if (script->type() == Script::TYPE_WASM) { | |
803 // TODO(clemensh): set breakpoint for wasm. | |
804 return false; | |
805 } | |
806 HandleScope scope(isolate_); | 888 HandleScope scope(isolate_); |
807 | 889 |
808 // Obtain shared function info for the function. | 890 Handle<DebugInfo> debug_info; |
809 Handle<Object> result = | 891 int start_position = 0; |
810 FindSharedFunctionInfoInScript(script, *source_position); | 892 if (script->type() == Script::TYPE_WASM) { |
811 if (result->IsUndefined(isolate_)) return false; | 893 Handle<wasm::WasmDebugInfo> wasm_debug( |
| 894 wasm::GetDebugInfo(handle(script->wasm_object(), isolate_)), isolate_); |
| 895 uint32_t func_index = script->wasm_function_index(); |
| 896 debug_info = handle( |
| 897 wasm::WasmDebugInfo::GetDebugInfo(wasm_debug, func_index), isolate_); |
| 898 } else { |
| 899 // Obtain shared function info for the function. |
| 900 Handle<Object> result = |
| 901 FindSharedFunctionInfoInScript(script, *source_position); |
| 902 if (result->IsUndefined(isolate_)) return false; |
812 | 903 |
813 // Make sure the function has set up the debug info. | 904 // Get debug info, create it if necessary. |
814 Handle<SharedFunctionInfo> shared = Handle<SharedFunctionInfo>::cast(result); | 905 Handle<SharedFunctionInfo> shared = |
815 if (!EnsureDebugInfo(shared, Handle<JSFunction>::null())) { | 906 Handle<SharedFunctionInfo>::cast(result); |
816 // Return if retrieving debug info failed. | 907 if (!EnsureDebugInfo(shared, Handle<JSFunction>::null())) { |
817 return false; | 908 // Return if retrieving debug info failed. |
| 909 return false; |
| 910 } |
| 911 debug_info = handle(shared->GetDebugInfo(), isolate_); |
| 912 start_position = shared->start_position(); |
818 } | 913 } |
819 | 914 |
820 // Find position within function. The script position might be before the | 915 // Find position within function. The script position might be before the |
821 // source position of the first function. | 916 // source position of the first function. |
822 int position; | 917 int position = |
823 if (shared->start_position() > *source_position) { | 918 start_position > *source_position ? 0 : *source_position - start_position; |
824 position = 0; | |
825 } else { | |
826 position = *source_position - shared->start_position(); | |
827 } | |
828 | 919 |
829 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); | |
830 // Source positions starts with zero. | 920 // Source positions starts with zero. |
831 DCHECK(position >= 0); | 921 DCHECK_LE(0, position); |
832 | 922 |
833 // Find the break point and change it. | 923 // Find the break point and change it. |
834 BreakLocation location = | 924 BreakLocation location = |
835 BreakLocation::FromPosition(debug_info, position, alignment); | 925 BreakLocation::FromPosition(debug_info, position, alignment); |
836 location.SetBreakPoint(break_point_object); | 926 location.SetBreakPoint(break_point_object); |
837 | 927 |
838 feature_tracker()->Track(DebugFeatureTracker::kBreakPoint); | 928 feature_tracker()->Track(DebugFeatureTracker::kBreakPoint); |
839 | 929 |
840 position = (alignment == STATEMENT_ALIGNED) ? location.statement_position() | 930 position = (alignment == STATEMENT_ALIGNED) ? location.statement_position() |
841 : location.position(); | 931 : location.position(); |
842 | 932 |
843 *source_position = position + shared->start_position(); | 933 *source_position = position + start_position; |
844 | 934 |
845 // At least one active break point now. | 935 // At least one active break point now. |
846 DCHECK(debug_info->GetBreakPointCount() > 0); | 936 DCHECK(debug_info->GetBreakPointCount() > 0); |
847 return true; | 937 return true; |
848 } | 938 } |
849 | 939 |
850 | 940 |
851 void Debug::ClearBreakPoint(Handle<Object> break_point_object) { | 941 void Debug::ClearBreakPoint(Handle<Object> break_point_object) { |
852 HandleScope scope(isolate_); | 942 HandleScope scope(isolate_); |
853 | 943 |
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1038 // Return if ensuring debug info failed. | 1128 // Return if ensuring debug info failed. |
1039 return; | 1129 return; |
1040 } | 1130 } |
1041 | 1131 |
1042 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); | 1132 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); |
1043 // Refresh frame summary if the code has been recompiled for debugging. | 1133 // Refresh frame summary if the code has been recompiled for debugging. |
1044 if (AbstractCode::cast(shared->code()) != *summary.abstract_code()) { | 1134 if (AbstractCode::cast(shared->code()) != *summary.abstract_code()) { |
1045 summary = FrameSummary::GetFirst(frame); | 1135 summary = FrameSummary::GetFirst(frame); |
1046 } | 1136 } |
1047 | 1137 |
1048 int call_offset = | 1138 int call_offset = CallOffsetFromCodeOffset(summary.code_offset(), frame); |
1049 CallOffsetFromCodeOffset(summary.code_offset(), frame->is_interpreted()); | |
1050 BreakLocation location = | 1139 BreakLocation location = |
1051 BreakLocation::FromCodeOffset(debug_info, call_offset); | 1140 BreakLocation::FromCodeOffset(debug_info, call_offset); |
1052 | 1141 |
1053 // Any step at a return is a step-out. | 1142 // Any step at a return is a step-out. |
1054 if (location.IsReturn()) step_action = StepOut; | 1143 if (location.IsReturn()) step_action = StepOut; |
1055 // A step-next at a tail call is a step-out. | 1144 // A step-next at a tail call is a step-out. |
1056 if (location.IsTailCall() && step_action == StepNext) step_action = StepOut; | 1145 if (location.IsTailCall() && step_action == StepNext) step_action = StepOut; |
1057 | 1146 |
1058 thread_local_.last_statement_position_ = | 1147 thread_local_.last_statement_position_ = |
1059 debug_info->abstract_code()->SourceStatementPosition( | 1148 debug_info->abstract_code()->SourceStatementPosition( |
(...skipping 536 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1596 return; | 1685 return; |
1597 } | 1686 } |
1598 // Move to next in list. | 1687 // Move to next in list. |
1599 prev = current; | 1688 prev = current; |
1600 current = current->next(); | 1689 current = current->next(); |
1601 } | 1690 } |
1602 | 1691 |
1603 UNREACHABLE(); | 1692 UNREACHABLE(); |
1604 } | 1693 } |
1605 | 1694 |
1606 void Debug::SetAfterBreakTarget(JavaScriptFrame* frame) { | 1695 void Debug::SetAfterBreakTarget(StandardFrame* frame) { |
1607 after_break_target_ = NULL; | 1696 after_break_target_ = NULL; |
1608 if (!LiveEdit::SetAfterBreakTarget(this)) { | 1697 if (!LiveEdit::SetAfterBreakTarget(this)) { |
1609 // Continue just after the slot. | 1698 // Continue just after the slot. |
1610 after_break_target_ = frame->pc(); | 1699 after_break_target_ = frame->pc(); |
1611 } | 1700 } |
1612 } | 1701 } |
1613 | 1702 |
1614 bool Debug::IsBreakAtReturn(JavaScriptFrame* frame) { | 1703 bool Debug::IsBreakAtReturn(JavaScriptFrame* frame) { |
1615 HandleScope scope(isolate_); | 1704 HandleScope scope(isolate_); |
1616 | 1705 |
(...skipping 691 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2308 // Store the previous break id, frame id and return value. | 2397 // Store the previous break id, frame id and return value. |
2309 break_id_ = debug_->break_id(); | 2398 break_id_ = debug_->break_id(); |
2310 break_frame_id_ = debug_->break_frame_id(); | 2399 break_frame_id_ = debug_->break_frame_id(); |
2311 return_value_ = debug_->return_value(); | 2400 return_value_ = debug_->return_value(); |
2312 | 2401 |
2313 // Create the new break info. If there is no proper frames there is no break | 2402 // Create the new break info. If there is no proper frames there is no break |
2314 // frame id. | 2403 // frame id. |
2315 StackTraceFrameIterator it(isolate()); | 2404 StackTraceFrameIterator it(isolate()); |
2316 bool has_frames = !it.done(); | 2405 bool has_frames = !it.done(); |
2317 // We don't currently support breaking inside wasm framess. | 2406 // We don't currently support breaking inside wasm framess. |
2318 DCHECK(!has_frames || !it.is_wasm()); | |
2319 debug_->thread_local_.break_frame_id_ = | 2407 debug_->thread_local_.break_frame_id_ = |
2320 has_frames ? it.frame()->id() : StackFrame::NO_ID; | 2408 has_frames ? it.frame()->id() : StackFrame::NO_ID; |
2321 debug_->SetNextBreakId(); | 2409 debug_->SetNextBreakId(); |
2322 | 2410 |
2323 debug_->UpdateState(); | 2411 debug_->UpdateState(); |
2324 // Make sure that debugger is loaded and enter the debugger context. | 2412 // Make sure that debugger is loaded and enter the debugger context. |
2325 // The previous context is kept in save_. | 2413 // The previous context is kept in save_. |
2326 failed_ = !debug_->is_loaded(); | 2414 failed_ = !debug_->is_loaded(); |
2327 if (!failed_) isolate()->set_context(*debug->debug_context()); | 2415 if (!failed_) isolate()->set_context(*debug->debug_context()); |
2328 } | 2416 } |
(...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2605 } | 2693 } |
2606 | 2694 |
2607 | 2695 |
2608 void LockingCommandMessageQueue::Clear() { | 2696 void LockingCommandMessageQueue::Clear() { |
2609 base::LockGuard<base::Mutex> lock_guard(&mutex_); | 2697 base::LockGuard<base::Mutex> lock_guard(&mutex_); |
2610 queue_.Clear(); | 2698 queue_.Clear(); |
2611 } | 2699 } |
2612 | 2700 |
2613 } // namespace internal | 2701 } // namespace internal |
2614 } // namespace v8 | 2702 } // namespace v8 |
OLD | NEW |