| 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 "v8.h" | 5 #include "v8.h" |
| 6 | 6 |
| 7 #include "api.h" | 7 #include "api.h" |
| 8 #include "arguments.h" | 8 #include "arguments.h" |
| 9 #include "bootstrapper.h" | 9 #include "bootstrapper.h" |
| 10 #include "code-stubs.h" | 10 #include "code-stubs.h" |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 73 | 73 |
| 74 | 74 |
| 75 BreakLocationIterator::~BreakLocationIterator() { | 75 BreakLocationIterator::~BreakLocationIterator() { |
| 76 ASSERT(reloc_iterator_ != NULL); | 76 ASSERT(reloc_iterator_ != NULL); |
| 77 ASSERT(reloc_iterator_original_ != NULL); | 77 ASSERT(reloc_iterator_original_ != NULL); |
| 78 delete reloc_iterator_; | 78 delete reloc_iterator_; |
| 79 delete reloc_iterator_original_; | 79 delete reloc_iterator_original_; |
| 80 } | 80 } |
| 81 | 81 |
| 82 | 82 |
| 83 // Check whether a code stub with the specified major key is a possible break |
| 84 // point location when looking for source break locations. |
| 85 static bool IsSourceBreakStub(Code* code) { |
| 86 CodeStub::Major major_key = CodeStub::GetMajorKey(code); |
| 87 return major_key == CodeStub::CallFunction; |
| 88 } |
| 89 |
| 90 |
| 91 // Check whether a code stub with the specified major key is a possible break |
| 92 // location. |
| 93 static bool IsBreakStub(Code* code) { |
| 94 CodeStub::Major major_key = CodeStub::GetMajorKey(code); |
| 95 return major_key == CodeStub::CallFunction; |
| 96 } |
| 97 |
| 98 |
| 83 void BreakLocationIterator::Next() { | 99 void BreakLocationIterator::Next() { |
| 84 DisallowHeapAllocation no_gc; | 100 DisallowHeapAllocation no_gc; |
| 85 ASSERT(!RinfoDone()); | 101 ASSERT(!RinfoDone()); |
| 86 | 102 |
| 87 // Iterate through reloc info for code and original code stopping at each | 103 // Iterate through reloc info for code and original code stopping at each |
| 88 // breakable code target. | 104 // breakable code target. |
| 89 bool first = break_point_ == -1; | 105 bool first = break_point_ == -1; |
| 90 while (!RinfoDone()) { | 106 while (!RinfoDone()) { |
| 91 if (!first) RinfoNext(); | 107 if (!first) RinfoNext(); |
| 92 first = false; | 108 first = false; |
| (...skipping 29 matching lines...) Expand all Loading... |
| 122 !code->is_compare_ic_stub() && | 138 !code->is_compare_ic_stub() && |
| 123 !code->is_to_boolean_ic_stub()) || | 139 !code->is_to_boolean_ic_stub()) || |
| 124 RelocInfo::IsConstructCall(rmode())) { | 140 RelocInfo::IsConstructCall(rmode())) { |
| 125 break_point_++; | 141 break_point_++; |
| 126 return; | 142 return; |
| 127 } | 143 } |
| 128 if (code->kind() == Code::STUB) { | 144 if (code->kind() == Code::STUB) { |
| 129 if (IsDebuggerStatement()) { | 145 if (IsDebuggerStatement()) { |
| 130 break_point_++; | 146 break_point_++; |
| 131 return; | 147 return; |
| 132 } | 148 } else if (type_ == ALL_BREAK_LOCATIONS) { |
| 133 if (type_ == ALL_BREAK_LOCATIONS) { | 149 if (IsBreakStub(code)) { |
| 134 if (Debug::IsBreakStub(code)) { | |
| 135 break_point_++; | 150 break_point_++; |
| 136 return; | 151 return; |
| 137 } | 152 } |
| 138 } else { | 153 } else { |
| 139 ASSERT(type_ == SOURCE_BREAK_LOCATIONS); | 154 ASSERT(type_ == SOURCE_BREAK_LOCATIONS); |
| 140 if (Debug::IsSourceBreakStub(code)) { | 155 if (IsSourceBreakStub(code)) { |
| 141 break_point_++; | 156 break_point_++; |
| 142 return; | 157 return; |
| 143 } | 158 } |
| 144 } | 159 } |
| 145 } | 160 } |
| 146 } | 161 } |
| 147 | 162 |
| 148 // Check for break at return. | 163 // Check for break at return. |
| 149 if (RelocInfo::IsJSReturn(rmode())) { | 164 if (RelocInfo::IsJSReturn(rmode())) { |
| 150 // Set the positions to the end of the function. | 165 // Set the positions to the end of the function. |
| (...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 415 if (RelocInfo::IsJSReturn(rmode())) { | 430 if (RelocInfo::IsJSReturn(rmode())) { |
| 416 return IsDebugBreakAtReturn(); | 431 return IsDebugBreakAtReturn(); |
| 417 } else if (IsDebugBreakSlot()) { | 432 } else if (IsDebugBreakSlot()) { |
| 418 return IsDebugBreakAtSlot(); | 433 return IsDebugBreakAtSlot(); |
| 419 } else { | 434 } else { |
| 420 return Debug::IsDebugBreak(rinfo()->target_address()); | 435 return Debug::IsDebugBreak(rinfo()->target_address()); |
| 421 } | 436 } |
| 422 } | 437 } |
| 423 | 438 |
| 424 | 439 |
| 440 // Find the builtin to use for invoking the debug break |
| 441 static Handle<Code> DebugBreakForIC(Handle<Code> code, RelocInfo::Mode mode) { |
| 442 Isolate* isolate = code->GetIsolate(); |
| 443 |
| 444 // Find the builtin debug break function matching the calling convention |
| 445 // used by the call site. |
| 446 if (code->is_inline_cache_stub()) { |
| 447 switch (code->kind()) { |
| 448 case Code::CALL_IC: |
| 449 return isolate->builtins()->CallICStub_DebugBreak(); |
| 450 |
| 451 case Code::LOAD_IC: |
| 452 return isolate->builtins()->LoadIC_DebugBreak(); |
| 453 |
| 454 case Code::STORE_IC: |
| 455 return isolate->builtins()->StoreIC_DebugBreak(); |
| 456 |
| 457 case Code::KEYED_LOAD_IC: |
| 458 return isolate->builtins()->KeyedLoadIC_DebugBreak(); |
| 459 |
| 460 case Code::KEYED_STORE_IC: |
| 461 return isolate->builtins()->KeyedStoreIC_DebugBreak(); |
| 462 |
| 463 case Code::COMPARE_NIL_IC: |
| 464 return isolate->builtins()->CompareNilIC_DebugBreak(); |
| 465 |
| 466 default: |
| 467 UNREACHABLE(); |
| 468 } |
| 469 } |
| 470 if (RelocInfo::IsConstructCall(mode)) { |
| 471 if (code->has_function_cache()) { |
| 472 return isolate->builtins()->CallConstructStub_Recording_DebugBreak(); |
| 473 } else { |
| 474 return isolate->builtins()->CallConstructStub_DebugBreak(); |
| 475 } |
| 476 } |
| 477 if (code->kind() == Code::STUB) { |
| 478 ASSERT(code->major_key() == CodeStub::CallFunction); |
| 479 return isolate->builtins()->CallFunctionStub_DebugBreak(); |
| 480 } |
| 481 |
| 482 UNREACHABLE(); |
| 483 return Handle<Code>::null(); |
| 484 } |
| 485 |
| 486 |
| 425 void BreakLocationIterator::SetDebugBreakAtIC() { | 487 void BreakLocationIterator::SetDebugBreakAtIC() { |
| 426 // Patch the original code with the current address as the current address | 488 // Patch the original code with the current address as the current address |
| 427 // might have changed by the inline caching since the code was copied. | 489 // might have changed by the inline caching since the code was copied. |
| 428 original_rinfo()->set_target_address(rinfo()->target_address()); | 490 original_rinfo()->set_target_address(rinfo()->target_address()); |
| 429 | 491 |
| 430 RelocInfo::Mode mode = rmode(); | 492 RelocInfo::Mode mode = rmode(); |
| 431 if (RelocInfo::IsCodeTarget(mode)) { | 493 if (RelocInfo::IsCodeTarget(mode)) { |
| 432 Address target = rinfo()->target_address(); | 494 Address target = rinfo()->target_address(); |
| 433 Handle<Code> target_code(Code::GetCodeFromTargetAddress(target)); | 495 Handle<Code> target_code(Code::GetCodeFromTargetAddress(target)); |
| 434 | 496 |
| 435 // Patch the code to invoke the builtin debug break function matching the | 497 // Patch the code to invoke the builtin debug break function matching the |
| 436 // calling convention used by the call site. | 498 // calling convention used by the call site. |
| 437 Handle<Code> dbgbrk_code(Debug::FindDebugBreak(target_code, mode)); | 499 Handle<Code> dbgbrk_code = DebugBreakForIC(target_code, mode); |
| 438 rinfo()->set_target_address(dbgbrk_code->entry()); | 500 rinfo()->set_target_address(dbgbrk_code->entry()); |
| 439 } | 501 } |
| 440 } | 502 } |
| 441 | 503 |
| 442 | 504 |
| 443 void BreakLocationIterator::ClearDebugBreakAtIC() { | 505 void BreakLocationIterator::ClearDebugBreakAtIC() { |
| 444 // Patch the code to the original invoke. | 506 // Patch the code to the original invoke. |
| 445 rinfo()->set_target_address(original_rinfo()->target_address()); | 507 rinfo()->set_target_address(original_rinfo()->target_address()); |
| 446 } | 508 } |
| 447 | 509 |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 497 thread_local_.break_frame_id_ = StackFrame::NO_ID; | 559 thread_local_.break_frame_id_ = StackFrame::NO_ID; |
| 498 thread_local_.last_step_action_ = StepNone; | 560 thread_local_.last_step_action_ = StepNone; |
| 499 thread_local_.last_statement_position_ = RelocInfo::kNoPosition; | 561 thread_local_.last_statement_position_ = RelocInfo::kNoPosition; |
| 500 thread_local_.step_count_ = 0; | 562 thread_local_.step_count_ = 0; |
| 501 thread_local_.last_fp_ = 0; | 563 thread_local_.last_fp_ = 0; |
| 502 thread_local_.queued_step_count_ = 0; | 564 thread_local_.queued_step_count_ = 0; |
| 503 thread_local_.step_into_fp_ = 0; | 565 thread_local_.step_into_fp_ = 0; |
| 504 thread_local_.step_out_fp_ = 0; | 566 thread_local_.step_out_fp_ = 0; |
| 505 // TODO(isolates): frames_are_dropped_? | 567 // TODO(isolates): frames_are_dropped_? |
| 506 thread_local_.debugger_entry_ = NULL; | 568 thread_local_.debugger_entry_ = NULL; |
| 507 thread_local_.has_pending_interrupt_ = false; | |
| 508 thread_local_.restarter_frame_function_pointer_ = NULL; | 569 thread_local_.restarter_frame_function_pointer_ = NULL; |
| 509 thread_local_.promise_on_stack_ = NULL; | 570 thread_local_.promise_on_stack_ = NULL; |
| 510 } | 571 } |
| 511 | 572 |
| 512 | 573 |
| 513 char* Debug::ArchiveDebug(char* storage) { | 574 char* Debug::ArchiveDebug(char* storage) { |
| 514 char* to = storage; | 575 char* to = storage; |
| 515 MemCopy(to, reinterpret_cast<char*>(&thread_local_), sizeof(ThreadLocal)); | 576 MemCopy(to, reinterpret_cast<char*>(&thread_local_), sizeof(ThreadLocal)); |
| 516 ThreadInit(); | 577 ThreadInit(); |
| 517 return storage + ArchiveSpacePerThread(); | 578 return storage + ArchiveSpacePerThread(); |
| 518 } | 579 } |
| 519 | 580 |
| 520 | 581 |
| 521 char* Debug::RestoreDebug(char* storage) { | 582 char* Debug::RestoreDebug(char* storage) { |
| 522 char* from = storage; | 583 char* from = storage; |
| 523 MemCopy(reinterpret_cast<char*>(&thread_local_), from, sizeof(ThreadLocal)); | 584 MemCopy(reinterpret_cast<char*>(&thread_local_), from, sizeof(ThreadLocal)); |
| 524 return storage + ArchiveSpacePerThread(); | 585 return storage + ArchiveSpacePerThread(); |
| 525 } | 586 } |
| 526 | 587 |
| 527 | 588 |
| 528 int Debug::ArchiveSpacePerThread() { | 589 int Debug::ArchiveSpacePerThread() { |
| 529 return sizeof(ThreadLocal); | 590 return sizeof(ThreadLocal); |
| 530 } | 591 } |
| 531 | 592 |
| 532 | 593 |
| 594 ScriptCache::ScriptCache(Isolate* isolate) : HashMap(HashMap::PointersMatch), |
| 595 isolate_(isolate), |
| 596 collected_scripts_(10) { |
| 597 Heap* heap = isolate_->heap(); |
| 598 HandleScope scope(isolate_); |
| 599 |
| 600 // Perform two GCs to get rid of all unreferenced scripts. The first GC gets |
| 601 // rid of all the cached script wrappers and the second gets rid of the |
| 602 // scripts which are no longer referenced. |
| 603 heap->CollectAllGarbage(Heap::kMakeHeapIterableMask, "ScriptCache"); |
| 604 heap->CollectAllGarbage(Heap::kMakeHeapIterableMask, "ScriptCache"); |
| 605 |
| 606 // Scan heap for Script objects. |
| 607 HeapIterator iterator(heap); |
| 608 DisallowHeapAllocation no_allocation; |
| 609 |
| 610 for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) { |
| 611 if (obj->IsScript() && Script::cast(obj)->HasValidSource()) { |
| 612 Add(Handle<Script>(Script::cast(obj))); |
| 613 } |
| 614 } |
| 615 } |
| 616 |
| 617 |
| 533 void ScriptCache::Add(Handle<Script> script) { | 618 void ScriptCache::Add(Handle<Script> script) { |
| 534 GlobalHandles* global_handles = isolate_->global_handles(); | 619 GlobalHandles* global_handles = isolate_->global_handles(); |
| 535 // Create an entry in the hash map for the script. | 620 // Create an entry in the hash map for the script. |
| 536 int id = script->id()->value(); | 621 int id = script->id()->value(); |
| 537 HashMap::Entry* entry = | 622 HashMap::Entry* entry = |
| 538 HashMap::Lookup(reinterpret_cast<void*>(id), Hash(id), true); | 623 HashMap::Lookup(reinterpret_cast<void*>(id), Hash(id), true); |
| 539 if (entry->value != NULL) { | 624 if (entry->value != NULL) { |
| 540 ASSERT(*script == *reinterpret_cast<Script**>(entry->value)); | 625 ASSERT(*script == *reinterpret_cast<Script**>(entry->value)); |
| 541 return; | 626 return; |
| 542 } | 627 } |
| (...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 778 ClearAllBreakPoints(); | 863 ClearAllBreakPoints(); |
| 779 ClearStepping(); | 864 ClearStepping(); |
| 780 | 865 |
| 781 // Match unmatched PromiseHandlePrologue calls. | 866 // Match unmatched PromiseHandlePrologue calls. |
| 782 while (thread_local_.promise_on_stack_) PromiseHandleEpilogue(); | 867 while (thread_local_.promise_on_stack_) PromiseHandleEpilogue(); |
| 783 | 868 |
| 784 // Return debugger is not loaded. | 869 // Return debugger is not loaded. |
| 785 if (!is_loaded()) return; | 870 if (!is_loaded()) return; |
| 786 | 871 |
| 787 // Clear the script cache. | 872 // Clear the script cache. |
| 788 DestroyScriptCache(); | 873 if (script_cache_ != NULL) { |
| 874 delete script_cache_; |
| 875 script_cache_ = NULL; |
| 876 } |
| 789 | 877 |
| 790 // Clear debugger context global handle. | 878 // Clear debugger context global handle. |
| 791 GlobalHandles::Destroy(Handle<Object>::cast(debug_context_).location()); | 879 GlobalHandles::Destroy(Handle<Object>::cast(debug_context_).location()); |
| 792 debug_context_ = Handle<Context>(); | 880 debug_context_ = Handle<Context>(); |
| 793 } | 881 } |
| 794 | 882 |
| 795 | 883 |
| 796 void Debug::Break(Arguments args, JavaScriptFrame* frame) { | 884 void Debug::Break(Arguments args, JavaScriptFrame* frame) { |
| 797 Heap* heap = isolate_->heap(); | 885 Heap* heap = isolate_->heap(); |
| 798 HandleScope scope(isolate_); | 886 HandleScope scope(isolate_); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 836 // triggered. | 924 // triggered. |
| 837 Handle<Object> break_points_hit(heap->undefined_value(), isolate_); | 925 Handle<Object> break_points_hit(heap->undefined_value(), isolate_); |
| 838 if (break_location_iterator.HasBreakPoint()) { | 926 if (break_location_iterator.HasBreakPoint()) { |
| 839 Handle<Object> break_point_objects = | 927 Handle<Object> break_point_objects = |
| 840 Handle<Object>(break_location_iterator.BreakPointObjects(), isolate_); | 928 Handle<Object>(break_location_iterator.BreakPointObjects(), isolate_); |
| 841 break_points_hit = CheckBreakPoints(break_point_objects); | 929 break_points_hit = CheckBreakPoints(break_point_objects); |
| 842 } | 930 } |
| 843 | 931 |
| 844 // If step out is active skip everything until the frame where we need to step | 932 // If step out is active skip everything until the frame where we need to step |
| 845 // out to is reached, unless real breakpoint is hit. | 933 // out to is reached, unless real breakpoint is hit. |
| 846 if (StepOutActive() && frame->fp() != step_out_fp() && | 934 if (StepOutActive() && |
| 935 frame->fp() != thread_local_.step_out_fp_ && |
| 847 break_points_hit->IsUndefined() ) { | 936 break_points_hit->IsUndefined() ) { |
| 848 // Step count should always be 0 for StepOut. | 937 // Step count should always be 0 for StepOut. |
| 849 ASSERT(thread_local_.step_count_ == 0); | 938 ASSERT(thread_local_.step_count_ == 0); |
| 850 } else if (!break_points_hit->IsUndefined() || | 939 } else if (!break_points_hit->IsUndefined() || |
| 851 (thread_local_.last_step_action_ != StepNone && | 940 (thread_local_.last_step_action_ != StepNone && |
| 852 thread_local_.step_count_ == 0)) { | 941 thread_local_.step_count_ == 0)) { |
| 853 // Notify debugger if a real break point is triggered or if performing | 942 // Notify debugger if a real break point is triggered or if performing |
| 854 // single stepping with no more steps to perform. Otherwise do another step. | 943 // single stepping with no more steps to perform. Otherwise do another step. |
| 855 | 944 |
| 856 // Clear all current stepping setup. | 945 // Clear all current stepping setup. |
| (...skipping 328 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1185 | 1274 |
| 1186 bool Debug::IsBreakOnException(ExceptionBreakType type) { | 1275 bool Debug::IsBreakOnException(ExceptionBreakType type) { |
| 1187 if (type == BreakUncaughtException) { | 1276 if (type == BreakUncaughtException) { |
| 1188 return break_on_uncaught_exception_; | 1277 return break_on_uncaught_exception_; |
| 1189 } else { | 1278 } else { |
| 1190 return break_on_exception_; | 1279 return break_on_exception_; |
| 1191 } | 1280 } |
| 1192 } | 1281 } |
| 1193 | 1282 |
| 1194 | 1283 |
| 1195 Debug::PromiseOnStack::PromiseOnStack(Isolate* isolate, | 1284 PromiseOnStack::PromiseOnStack(Isolate* isolate, |
| 1196 PromiseOnStack* prev, | 1285 PromiseOnStack* prev, |
| 1197 Handle<JSFunction> getter) | 1286 Handle<JSFunction> getter) |
| 1198 : isolate_(isolate), prev_(prev) { | 1287 : isolate_(isolate), prev_(prev) { |
| 1199 handler_ = StackHandler::FromAddress( | 1288 handler_ = StackHandler::FromAddress( |
| 1200 Isolate::handler(isolate->thread_local_top())); | 1289 Isolate::handler(isolate->thread_local_top())); |
| 1201 getter_ = Handle<JSFunction>::cast( | 1290 getter_ = Handle<JSFunction>::cast( |
| 1202 isolate->global_handles()->Create(*getter)); | 1291 isolate->global_handles()->Create(*getter)); |
| 1203 } | 1292 } |
| 1204 | 1293 |
| 1205 | 1294 |
| 1206 Debug::PromiseOnStack::~PromiseOnStack() { | 1295 PromiseOnStack::~PromiseOnStack() { |
| 1207 isolate_->global_handles()->Destroy(Handle<Object>::cast(getter_).location()); | 1296 isolate_->global_handles()->Destroy(Handle<Object>::cast(getter_).location()); |
| 1208 } | 1297 } |
| 1209 | 1298 |
| 1210 | 1299 |
| 1211 void Debug::PromiseHandlePrologue(Handle<JSFunction> promise_getter) { | 1300 void Debug::PromiseHandlePrologue(Handle<JSFunction> promise_getter) { |
| 1212 PromiseOnStack* prev = thread_local_.promise_on_stack_; | 1301 PromiseOnStack* prev = thread_local_.promise_on_stack_; |
| 1213 thread_local_.promise_on_stack_ = | 1302 thread_local_.promise_on_stack_ = |
| 1214 new PromiseOnStack(isolate_, prev, promise_getter); | 1303 new PromiseOnStack(isolate_, prev, promise_getter); |
| 1215 } | 1304 } |
| 1216 | 1305 |
| (...skipping 306 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1523 | 1612 |
| 1524 | 1613 |
| 1525 // Check whether the code object at the specified address is a debug break code | 1614 // Check whether the code object at the specified address is a debug break code |
| 1526 // object. | 1615 // object. |
| 1527 bool Debug::IsDebugBreak(Address addr) { | 1616 bool Debug::IsDebugBreak(Address addr) { |
| 1528 Code* code = Code::GetCodeFromTargetAddress(addr); | 1617 Code* code = Code::GetCodeFromTargetAddress(addr); |
| 1529 return code->is_debug_stub() && code->extra_ic_state() == DEBUG_BREAK; | 1618 return code->is_debug_stub() && code->extra_ic_state() == DEBUG_BREAK; |
| 1530 } | 1619 } |
| 1531 | 1620 |
| 1532 | 1621 |
| 1533 // Check whether a code stub with the specified major key is a possible break | |
| 1534 // point location when looking for source break locations. | |
| 1535 bool Debug::IsSourceBreakStub(Code* code) { | |
| 1536 CodeStub::Major major_key = CodeStub::GetMajorKey(code); | |
| 1537 return major_key == CodeStub::CallFunction; | |
| 1538 } | |
| 1539 | 1622 |
| 1540 | 1623 |
| 1541 // Check whether a code stub with the specified major key is a possible break | |
| 1542 // location. | |
| 1543 bool Debug::IsBreakStub(Code* code) { | |
| 1544 CodeStub::Major major_key = CodeStub::GetMajorKey(code); | |
| 1545 return major_key == CodeStub::CallFunction; | |
| 1546 } | |
| 1547 | |
| 1548 | |
| 1549 // Find the builtin to use for invoking the debug break | |
| 1550 Handle<Code> Debug::FindDebugBreak(Handle<Code> code, RelocInfo::Mode mode) { | |
| 1551 Isolate* isolate = code->GetIsolate(); | |
| 1552 | |
| 1553 // Find the builtin debug break function matching the calling convention | |
| 1554 // used by the call site. | |
| 1555 if (code->is_inline_cache_stub()) { | |
| 1556 switch (code->kind()) { | |
| 1557 case Code::CALL_IC: | |
| 1558 return isolate->builtins()->CallICStub_DebugBreak(); | |
| 1559 | |
| 1560 case Code::LOAD_IC: | |
| 1561 return isolate->builtins()->LoadIC_DebugBreak(); | |
| 1562 | |
| 1563 case Code::STORE_IC: | |
| 1564 return isolate->builtins()->StoreIC_DebugBreak(); | |
| 1565 | |
| 1566 case Code::KEYED_LOAD_IC: | |
| 1567 return isolate->builtins()->KeyedLoadIC_DebugBreak(); | |
| 1568 | |
| 1569 case Code::KEYED_STORE_IC: | |
| 1570 return isolate->builtins()->KeyedStoreIC_DebugBreak(); | |
| 1571 | |
| 1572 case Code::COMPARE_NIL_IC: | |
| 1573 return isolate->builtins()->CompareNilIC_DebugBreak(); | |
| 1574 | |
| 1575 default: | |
| 1576 UNREACHABLE(); | |
| 1577 } | |
| 1578 } | |
| 1579 if (RelocInfo::IsConstructCall(mode)) { | |
| 1580 if (code->has_function_cache()) { | |
| 1581 return isolate->builtins()->CallConstructStub_Recording_DebugBreak(); | |
| 1582 } else { | |
| 1583 return isolate->builtins()->CallConstructStub_DebugBreak(); | |
| 1584 } | |
| 1585 } | |
| 1586 if (code->kind() == Code::STUB) { | |
| 1587 ASSERT(code->major_key() == CodeStub::CallFunction); | |
| 1588 return isolate->builtins()->CallFunctionStub_DebugBreak(); | |
| 1589 } | |
| 1590 | |
| 1591 UNREACHABLE(); | |
| 1592 return Handle<Code>::null(); | |
| 1593 } | |
| 1594 | |
| 1595 | 1624 |
| 1596 // Simple function for returning the source positions for active break points. | 1625 // Simple function for returning the source positions for active break points. |
| 1597 Handle<Object> Debug::GetSourceBreakLocations( | 1626 Handle<Object> Debug::GetSourceBreakLocations( |
| 1598 Handle<SharedFunctionInfo> shared, | 1627 Handle<SharedFunctionInfo> shared, |
| 1599 BreakPositionAlignment position_alignment) { | 1628 BreakPositionAlignment position_alignment) { |
| 1600 Isolate* isolate = shared->GetIsolate(); | 1629 Isolate* isolate = shared->GetIsolate(); |
| 1601 Heap* heap = isolate->heap(); | 1630 Heap* heap = isolate->heap(); |
| 1602 if (!HasDebugInfo(shared)) { | 1631 if (!HasDebugInfo(shared)) { |
| 1603 return Handle<Object>(heap->undefined_value(), isolate); | 1632 return Handle<Object>(heap->undefined_value(), isolate); |
| 1604 } | 1633 } |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1648 // For constructor functions skip another frame. | 1677 // For constructor functions skip another frame. |
| 1649 if (is_constructor) { | 1678 if (is_constructor) { |
| 1650 ASSERT(it.frame()->is_construct()); | 1679 ASSERT(it.frame()->is_construct()); |
| 1651 it.Advance(); | 1680 it.Advance(); |
| 1652 } | 1681 } |
| 1653 fp = it.frame()->fp(); | 1682 fp = it.frame()->fp(); |
| 1654 } | 1683 } |
| 1655 | 1684 |
| 1656 // Flood the function with one-shot break points if it is called from where | 1685 // Flood the function with one-shot break points if it is called from where |
| 1657 // step into was requested. | 1686 // step into was requested. |
| 1658 if (fp == step_in_fp()) { | 1687 if (fp == thread_local_.step_into_fp_) { |
| 1659 if (function->shared()->bound()) { | 1688 if (function->shared()->bound()) { |
| 1660 // Handle Function.prototype.bind | 1689 // Handle Function.prototype.bind |
| 1661 Debug::FloodBoundFunctionWithOneShot(function); | 1690 Debug::FloodBoundFunctionWithOneShot(function); |
| 1662 } else if (!function->IsNative()) { | 1691 } else if (!function->IsNative()) { |
| 1663 // Don't allow step into functions in the native context. | 1692 // Don't allow step into functions in the native context. |
| 1664 if (function->shared()->code() == | 1693 if (function->shared()->code() == |
| 1665 isolate->builtins()->builtin(Builtins::kFunctionApply) || | 1694 isolate->builtins()->builtin(Builtins::kFunctionApply) || |
| 1666 function->shared()->code() == | 1695 function->shared()->code() == |
| 1667 isolate->builtins()->builtin(Builtins::kFunctionCall)) { | 1696 isolate->builtins()->builtin(Builtins::kFunctionCall)) { |
| 1668 // Handle function.apply and function.call separately to flood the | 1697 // Handle function.apply and function.call separately to flood the |
| (...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1905 | 1934 |
| 1906 | 1935 |
| 1907 class ActiveFunctionsRedirector : public ThreadVisitor { | 1936 class ActiveFunctionsRedirector : public ThreadVisitor { |
| 1908 public: | 1937 public: |
| 1909 void VisitThread(Isolate* isolate, ThreadLocalTop* top) { | 1938 void VisitThread(Isolate* isolate, ThreadLocalTop* top) { |
| 1910 RedirectActivationsToRecompiledCodeOnThread(isolate, top); | 1939 RedirectActivationsToRecompiledCodeOnThread(isolate, top); |
| 1911 } | 1940 } |
| 1912 }; | 1941 }; |
| 1913 | 1942 |
| 1914 | 1943 |
| 1915 void Debug::EnsureFunctionHasDebugBreakSlots(Handle<JSFunction> function) { | 1944 static void EnsureFunctionHasDebugBreakSlots(Handle<JSFunction> function) { |
| 1916 if (function->code()->kind() == Code::FUNCTION && | 1945 if (function->code()->kind() == Code::FUNCTION && |
| 1917 function->code()->has_debug_break_slots()) { | 1946 function->code()->has_debug_break_slots()) { |
| 1918 // Nothing to do. Function code already had debug break slots. | 1947 // Nothing to do. Function code already had debug break slots. |
| 1919 return; | 1948 return; |
| 1920 } | 1949 } |
| 1921 // Make sure that the shared full code is compiled with debug | 1950 // Make sure that the shared full code is compiled with debug |
| 1922 // break slots. | 1951 // break slots. |
| 1923 if (!function->shared()->code()->has_debug_break_slots()) { | 1952 if (!function->shared()->code()->has_debug_break_slots()) { |
| 1924 MaybeHandle<Code> code = Compiler::GetCodeForDebugging(function); | 1953 MaybeHandle<Code> code = Compiler::GetCodeForDebugging(function); |
| 1925 // Recompilation can fail. In that case leave the code as it was. | 1954 // Recompilation can fail. In that case leave the code as it was. |
| 1926 if (!code.is_null()) function->ReplaceCode(*code.ToHandleChecked()); | 1955 if (!code.is_null()) function->ReplaceCode(*code.ToHandleChecked()); |
| 1927 } else { | 1956 } else { |
| 1928 // Simply use shared code if it has debug break slots. | 1957 // Simply use shared code if it has debug break slots. |
| 1929 function->ReplaceCode(function->shared()->code()); | 1958 function->ReplaceCode(function->shared()->code()); |
| 1930 } | 1959 } |
| 1931 } | 1960 } |
| 1932 | 1961 |
| 1933 | 1962 |
| 1934 void Debug::RecompileAndRelocateSuspendedGenerators( | 1963 static void RecompileAndRelocateSuspendedGenerators( |
| 1935 const List<Handle<JSGeneratorObject> > &generators) { | 1964 const List<Handle<JSGeneratorObject> > &generators) { |
| 1936 for (int i = 0; i < generators.length(); i++) { | 1965 for (int i = 0; i < generators.length(); i++) { |
| 1937 Handle<JSFunction> fun(generators[i]->function()); | 1966 Handle<JSFunction> fun(generators[i]->function()); |
| 1938 | 1967 |
| 1939 EnsureFunctionHasDebugBreakSlots(fun); | 1968 EnsureFunctionHasDebugBreakSlots(fun); |
| 1940 | 1969 |
| 1941 int code_offset = generators[i]->continuation(); | 1970 int code_offset = generators[i]->continuation(); |
| 1942 int pc_offset = ComputePcOffsetFromCodeOffset(fun->code(), code_offset); | 1971 int pc_offset = ComputePcOffsetFromCodeOffset(fun->code(), code_offset); |
| 1943 generators[i]->set_continuation(pc_offset); | 1972 generators[i]->set_continuation(pc_offset); |
| 1944 } | 1973 } |
| (...skipping 492 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2437 isolate_->global_object(), | 2466 isolate_->global_object(), |
| 2438 "ClearMirrorCache").ToHandleChecked(); | 2467 "ClearMirrorCache").ToHandleChecked(); |
| 2439 ASSERT(fun->IsJSFunction()); | 2468 ASSERT(fun->IsJSFunction()); |
| 2440 Execution::TryCall(Handle<JSFunction>::cast(fun), | 2469 Execution::TryCall(Handle<JSFunction>::cast(fun), |
| 2441 Handle<JSObject>(Debug::debug_context()->global_object()), | 2470 Handle<JSObject>(Debug::debug_context()->global_object()), |
| 2442 0, | 2471 0, |
| 2443 NULL); | 2472 NULL); |
| 2444 } | 2473 } |
| 2445 | 2474 |
| 2446 | 2475 |
| 2447 void Debug::CreateScriptCache() { | |
| 2448 Heap* heap = isolate_->heap(); | |
| 2449 HandleScope scope(isolate_); | |
| 2450 | |
| 2451 // Perform two GCs to get rid of all unreferenced scripts. The first GC gets | |
| 2452 // rid of all the cached script wrappers and the second gets rid of the | |
| 2453 // scripts which are no longer referenced. The second also sweeps precisely, | |
| 2454 // which saves us doing yet another GC to make the heap iterable. | |
| 2455 heap->CollectAllGarbage(Heap::kNoGCFlags, "Debug::CreateScriptCache"); | |
| 2456 | |
| 2457 ASSERT(script_cache_ == NULL); | |
| 2458 script_cache_ = new ScriptCache(isolate_); | |
| 2459 | |
| 2460 // Scan heap for Script objects. | |
| 2461 int count = 0; | |
| 2462 HeapIterator iterator(heap); | |
| 2463 | |
| 2464 for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) { | |
| 2465 if (obj->IsScript() && Script::cast(obj)->HasValidSource()) { | |
| 2466 script_cache_->Add(Handle<Script>(Script::cast(obj))); | |
| 2467 count++; | |
| 2468 } | |
| 2469 } | |
| 2470 } | |
| 2471 | |
| 2472 | |
| 2473 void Debug::DestroyScriptCache() { | |
| 2474 // Get rid of the script cache if it was created. | |
| 2475 if (script_cache_ != NULL) { | |
| 2476 delete script_cache_; | |
| 2477 script_cache_ = NULL; | |
| 2478 } | |
| 2479 } | |
| 2480 | |
| 2481 | |
| 2482 void Debug::AddScriptToScriptCache(Handle<Script> script) { | |
| 2483 if (script_cache_ != NULL) { | |
| 2484 script_cache_->Add(script); | |
| 2485 } | |
| 2486 } | |
| 2487 | |
| 2488 | |
| 2489 Handle<FixedArray> Debug::GetLoadedScripts() { | 2476 Handle<FixedArray> Debug::GetLoadedScripts() { |
| 2490 // Create and fill the script cache when the loaded scripts is requested for | 2477 // Create and fill the script cache when the loaded scripts is requested for |
| 2491 // the first time. | 2478 // the first time. |
| 2492 if (script_cache_ == NULL) { | 2479 if (script_cache_ == NULL) script_cache_ = new ScriptCache(isolate_); |
| 2493 CreateScriptCache(); | |
| 2494 } | |
| 2495 | |
| 2496 // If the script cache is not active just return an empty array. | |
| 2497 ASSERT(script_cache_ != NULL); | |
| 2498 if (script_cache_ == NULL) { | |
| 2499 isolate_->factory()->NewFixedArray(0); | |
| 2500 } | |
| 2501 | 2480 |
| 2502 // Perform GC to get unreferenced scripts evicted from the cache before | 2481 // Perform GC to get unreferenced scripts evicted from the cache before |
| 2503 // returning the content. | 2482 // returning the content. |
| 2504 isolate_->heap()->CollectAllGarbage(Heap::kNoGCFlags, | 2483 isolate_->heap()->CollectAllGarbage(Heap::kNoGCFlags, |
| 2505 "Debug::GetLoadedScripts"); | 2484 "Debug::GetLoadedScripts"); |
| 2506 | 2485 |
| 2507 // Get the scripts from the cache. | 2486 // Get the scripts from the cache. |
| 2508 return script_cache_->GetScripts(); | 2487 return script_cache_->GetScripts(); |
| 2509 } | 2488 } |
| 2510 | 2489 |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2597 Handle<Object> exec_state; | 2576 Handle<Object> exec_state; |
| 2598 if (!MakeExecutionState().ToHandle(&exec_state)) return MaybeHandle<Object>(); | 2577 if (!MakeExecutionState().ToHandle(&exec_state)) return MaybeHandle<Object>(); |
| 2599 // Create the script collected event object. | 2578 // Create the script collected event object. |
| 2600 Handle<Object> id_object = Handle<Smi>(Smi::FromInt(id), isolate_); | 2579 Handle<Object> id_object = Handle<Smi>(Smi::FromInt(id), isolate_); |
| 2601 Handle<Object> argv[] = { exec_state, id_object }; | 2580 Handle<Object> argv[] = { exec_state, id_object }; |
| 2602 return MakeJSObject("MakeScriptCollectedEvent", ARRAY_SIZE(argv), argv); | 2581 return MakeJSObject("MakeScriptCollectedEvent", ARRAY_SIZE(argv), argv); |
| 2603 } | 2582 } |
| 2604 | 2583 |
| 2605 | 2584 |
| 2606 void Debug::OnException(Handle<Object> exception, bool uncaught) { | 2585 void Debug::OnException(Handle<Object> exception, bool uncaught) { |
| 2586 if (is_entered() || ignore_events()) return; |
| 2587 |
| 2607 HandleScope scope(isolate_); | 2588 HandleScope scope(isolate_); |
| 2608 | |
| 2609 // Bail out based on state or if there is no listener for this event | |
| 2610 if (is_entered()) return; | |
| 2611 if (!EventActive()) return; | |
| 2612 | |
| 2613 Handle<Object> promise = GetPromiseForUncaughtException(); | 2589 Handle<Object> promise = GetPromiseForUncaughtException(); |
| 2614 uncaught |= !promise->IsUndefined(); | 2590 uncaught |= !promise->IsUndefined(); |
| 2615 | 2591 |
| 2616 // Bail out if exception breaks are not active | 2592 // Bail out if exception breaks are not active |
| 2617 if (uncaught) { | 2593 if (uncaught) { |
| 2618 // Uncaught exceptions are reported by either flags. | 2594 // Uncaught exceptions are reported by either flags. |
| 2619 if (!(break_on_uncaught_exception() || break_on_exception())) return; | 2595 if (!(break_on_uncaught_exception_ || break_on_exception_)) return; |
| 2620 } else { | 2596 } else { |
| 2621 // Caught exceptions are reported is activated. | 2597 // Caught exceptions are reported is activated. |
| 2622 if (!break_on_exception()) return; | 2598 if (!break_on_exception_) return; |
| 2623 } | 2599 } |
| 2624 | 2600 |
| 2625 // Enter the debugger. | 2601 // Enter the debugger. |
| 2626 EnterDebugger debugger(isolate_); | 2602 EnterDebugger debugger(isolate_); |
| 2627 if (debugger.FailedToEnter()) return; | 2603 if (debugger.FailedToEnter()) return; |
| 2628 | 2604 |
| 2629 // Clear all current stepping setup. | 2605 // Clear all current stepping setup. |
| 2630 ClearStepping(); | 2606 ClearStepping(); |
| 2631 | 2607 |
| 2632 // Create the event data object. | 2608 // Create the event data object. |
| 2633 Handle<Object> event_data; | 2609 Handle<Object> event_data; |
| 2634 // Bail out and don't call debugger if exception. | 2610 // Bail out and don't call debugger if exception. |
| 2635 if (!MakeExceptionEvent( | 2611 if (!MakeExceptionEvent( |
| 2636 exception, uncaught, promise).ToHandle(&event_data)) { | 2612 exception, uncaught, promise).ToHandle(&event_data)) { |
| 2637 return; | 2613 return; |
| 2638 } | 2614 } |
| 2639 | 2615 |
| 2640 // Process debug event. | 2616 // Process debug event. |
| 2641 ProcessDebugEvent(v8::Exception, Handle<JSObject>::cast(event_data), false); | 2617 ProcessDebugEvent(v8::Exception, Handle<JSObject>::cast(event_data), false); |
| 2642 // Return to continue execution from where the exception was thrown. | 2618 // Return to continue execution from where the exception was thrown. |
| 2643 } | 2619 } |
| 2644 | 2620 |
| 2645 | 2621 |
| 2646 void Debug::OnDebugBreak(Handle<Object> break_points_hit, | 2622 void Debug::OnDebugBreak(Handle<Object> break_points_hit, |
| 2647 bool auto_continue) { | 2623 bool auto_continue) { |
| 2648 HandleScope scope(isolate_); | |
| 2649 | |
| 2650 // Debugger has already been entered by caller. | 2624 // Debugger has already been entered by caller. |
| 2651 ASSERT(isolate_->context() == *debug_context()); | 2625 ASSERT(isolate_->context() == *debug_context()); |
| 2626 // Bail out if there is no listener for this event |
| 2627 if (ignore_events()) return; |
| 2652 | 2628 |
| 2653 // Bail out if there is no listener for this event | 2629 HandleScope scope(isolate_); |
| 2654 if (!EventActive()) return; | |
| 2655 | |
| 2656 // Create the event data object. | 2630 // Create the event data object. |
| 2657 Handle<Object> event_data; | 2631 Handle<Object> event_data; |
| 2658 // Bail out and don't call debugger if exception. | 2632 // Bail out and don't call debugger if exception. |
| 2659 if (!MakeBreakEvent(break_points_hit).ToHandle(&event_data)) return; | 2633 if (!MakeBreakEvent(break_points_hit).ToHandle(&event_data)) return; |
| 2660 | 2634 |
| 2661 // Process debug event. | 2635 // Process debug event. |
| 2662 ProcessDebugEvent(v8::Break, | 2636 ProcessDebugEvent(v8::Break, |
| 2663 Handle<JSObject>::cast(event_data), | 2637 Handle<JSObject>::cast(event_data), |
| 2664 auto_continue); | 2638 auto_continue); |
| 2665 } | 2639 } |
| 2666 | 2640 |
| 2667 | 2641 |
| 2668 void Debug::OnBeforeCompile(Handle<Script> script) { | 2642 void Debug::OnBeforeCompile(Handle<Script> script) { |
| 2643 if (is_entered() || ignore_events()) return; |
| 2644 |
| 2669 HandleScope scope(isolate_); | 2645 HandleScope scope(isolate_); |
| 2670 | |
| 2671 // Bail out based on state or if there is no listener for this event | |
| 2672 if (is_entered()) return; | |
| 2673 if (!EventActive()) return; | |
| 2674 | |
| 2675 // Enter the debugger. | 2646 // Enter the debugger. |
| 2676 EnterDebugger debugger(isolate_); | 2647 EnterDebugger debugger(isolate_); |
| 2677 if (debugger.FailedToEnter()) return; | 2648 if (debugger.FailedToEnter()) return; |
| 2678 | 2649 |
| 2679 // Create the event data object. | 2650 // Create the event data object. |
| 2680 Handle<Object> event_data; | 2651 Handle<Object> event_data; |
| 2681 // Bail out and don't call debugger if exception. | 2652 // Bail out and don't call debugger if exception. |
| 2682 if (!MakeCompileEvent(script, true).ToHandle(&event_data)) return; | 2653 if (!MakeCompileEvent(script, true).ToHandle(&event_data)) return; |
| 2683 | 2654 |
| 2684 // Process debug event. | 2655 // Process debug event. |
| 2685 ProcessDebugEvent(v8::BeforeCompile, | 2656 ProcessDebugEvent(v8::BeforeCompile, |
| 2686 Handle<JSObject>::cast(event_data), | 2657 Handle<JSObject>::cast(event_data), |
| 2687 true); | 2658 true); |
| 2688 } | 2659 } |
| 2689 | 2660 |
| 2690 | 2661 |
| 2691 // Handle debugger actions when a new script is compiled. | 2662 // Handle debugger actions when a new script is compiled. |
| 2692 void Debug::OnAfterCompile(Handle<Script> script, | 2663 void Debug::OnAfterCompile(Handle<Script> script, |
| 2693 AfterCompileFlags after_compile_flags) { | 2664 AfterCompileFlags after_compile_flags) { |
| 2694 HandleScope scope(isolate_); | |
| 2695 | |
| 2696 // Add the newly compiled script to the script cache. | 2665 // Add the newly compiled script to the script cache. |
| 2697 AddScriptToScriptCache(script); | 2666 if (script_cache_ != NULL) script_cache_->Add(script); |
| 2698 | 2667 |
| 2699 // No more to do if not debugging. | 2668 // No more to do if not debugging. |
| 2700 if (!EventActive()) return; | 2669 if (is_entered() || ignore_events()) return; |
| 2701 | 2670 |
| 2671 HandleScope scope(isolate_); |
| 2702 // Store whether in debugger before entering debugger. | 2672 // Store whether in debugger before entering debugger. |
| 2703 bool in_debugger = is_entered(); | 2673 bool in_debugger = is_entered(); |
| 2704 | 2674 |
| 2705 // Enter the debugger. | 2675 // Enter the debugger. |
| 2706 EnterDebugger debugger(isolate_); | 2676 EnterDebugger debugger(isolate_); |
| 2707 if (debugger.FailedToEnter()) return; | 2677 if (debugger.FailedToEnter()) return; |
| 2708 | 2678 |
| 2709 // If debugging there might be script break points registered for this | 2679 // If debugging there might be script break points registered for this |
| 2710 // script. Make sure that these break points are set. | 2680 // script. Make sure that these break points are set. |
| 2711 | 2681 |
| (...skipping 29 matching lines...) Expand all Loading... |
| 2741 Handle<Object> event_data; | 2711 Handle<Object> event_data; |
| 2742 // Bail out and don't call debugger if exception. | 2712 // Bail out and don't call debugger if exception. |
| 2743 if (!MakeCompileEvent(script, false).ToHandle(&event_data)) return; | 2713 if (!MakeCompileEvent(script, false).ToHandle(&event_data)) return; |
| 2744 | 2714 |
| 2745 // Process debug event. | 2715 // Process debug event. |
| 2746 ProcessDebugEvent(v8::AfterCompile, Handle<JSObject>::cast(event_data), true); | 2716 ProcessDebugEvent(v8::AfterCompile, Handle<JSObject>::cast(event_data), true); |
| 2747 } | 2717 } |
| 2748 | 2718 |
| 2749 | 2719 |
| 2750 void Debug::OnScriptCollected(int id) { | 2720 void Debug::OnScriptCollected(int id) { |
| 2721 if (is_entered() || ignore_events()) return; |
| 2722 |
| 2751 HandleScope scope(isolate_); | 2723 HandleScope scope(isolate_); |
| 2752 | |
| 2753 // No more to do if not debugging. | |
| 2754 if (is_entered()) return; | |
| 2755 if (!EventActive()) return; | |
| 2756 | |
| 2757 // Enter the debugger. | 2724 // Enter the debugger. |
| 2758 EnterDebugger debugger(isolate_); | 2725 EnterDebugger debugger(isolate_); |
| 2759 if (debugger.FailedToEnter()) return; | 2726 if (debugger.FailedToEnter()) return; |
| 2760 | 2727 |
| 2761 // Create the script collected state object. | 2728 // Create the script collected state object. |
| 2762 Handle<Object> event_data; | 2729 Handle<Object> event_data; |
| 2763 // Bail out and don't call debugger if exception. | 2730 // Bail out and don't call debugger if exception. |
| 2764 if (!MakeScriptCollectedEvent(id).ToHandle(&event_data)) return; | 2731 if (!MakeScriptCollectedEvent(id).ToHandle(&event_data)) return; |
| 2765 | 2732 |
| 2766 // Process debug event. | 2733 // Process debug event. |
| 2767 ProcessDebugEvent(v8::ScriptCollected, | 2734 ProcessDebugEvent(v8::ScriptCollected, |
| 2768 Handle<JSObject>::cast(event_data), | 2735 Handle<JSObject>::cast(event_data), |
| 2769 true); | 2736 true); |
| 2770 } | 2737 } |
| 2771 | 2738 |
| 2772 | 2739 |
| 2773 void Debug::ProcessDebugEvent(v8::DebugEvent event, | 2740 void Debug::ProcessDebugEvent(v8::DebugEvent event, |
| 2774 Handle<JSObject> event_data, | 2741 Handle<JSObject> event_data, |
| 2775 bool auto_continue) { | 2742 bool auto_continue) { |
| 2776 HandleScope scope(isolate_); | 2743 HandleScope scope(isolate_); |
| 2777 | 2744 |
| 2778 // Clear any pending debug break if this is a real break. | |
| 2779 if (!auto_continue) thread_local_.has_pending_interrupt_ = false; | |
| 2780 | |
| 2781 // Create the execution state. | 2745 // Create the execution state. |
| 2782 Handle<Object> exec_state; | 2746 Handle<Object> exec_state; |
| 2783 // Bail out and don't call debugger if exception. | 2747 // Bail out and don't call debugger if exception. |
| 2784 if (!MakeExecutionState().ToHandle(&exec_state)) return; | 2748 if (!MakeExecutionState().ToHandle(&exec_state)) return; |
| 2785 | 2749 |
| 2786 // First notify the message handler if any. | 2750 // First notify the message handler if any. |
| 2787 if (message_handler_ != NULL) { | 2751 if (message_handler_ != NULL) { |
| 2788 NotifyMessageHandler(event, | 2752 NotifyMessageHandler(event, |
| 2789 Handle<JSObject>::cast(exec_state), | 2753 Handle<JSObject>::cast(exec_state), |
| 2790 event_data, | 2754 event_data, |
| (...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3088 Handle<Object> argv[] = { exec_state, data }; | 3052 Handle<Object> argv[] = { exec_state, data }; |
| 3089 return Execution::Call( | 3053 return Execution::Call( |
| 3090 isolate_, | 3054 isolate_, |
| 3091 fun, | 3055 fun, |
| 3092 Handle<Object>(debug_context()->global_proxy(), isolate_), | 3056 Handle<Object>(debug_context()->global_proxy(), isolate_), |
| 3093 ARRAY_SIZE(argv), | 3057 ARRAY_SIZE(argv), |
| 3094 argv); | 3058 argv); |
| 3095 } | 3059 } |
| 3096 | 3060 |
| 3097 | 3061 |
| 3098 void Debug::DebugBreakHelper() { | 3062 void Debug::HandleDebugBreak() { |
| 3099 // Ignore debug break during bootstrapping. | 3063 // Ignore debug break during bootstrapping. |
| 3100 if (isolate_->bootstrapper()->IsActive()) return; | 3064 if (isolate_->bootstrapper()->IsActive()) return; |
| 3101 // Just continue if breaks are disabled. | 3065 // Just continue if breaks are disabled. |
| 3102 if (break_disabled_) return; | 3066 if (break_disabled_) return; |
| 3103 // Ignore debug break if debugger is not active. | 3067 // Ignore debug break if debugger is not active. |
| 3104 if (!is_active()) return; | 3068 if (!is_active()) return; |
| 3105 | 3069 |
| 3106 StackLimitCheck check(isolate_); | 3070 StackLimitCheck check(isolate_); |
| 3107 if (check.HasOverflowed()) return; | 3071 if (check.HasOverflowed()) return; |
| 3108 | 3072 |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3154 // Link recursive debugger entry. | 3118 // Link recursive debugger entry. |
| 3155 debug->thread_local_.debugger_entry_ = this; | 3119 debug->thread_local_.debugger_entry_ = this; |
| 3156 | 3120 |
| 3157 // Store the previous break id and frame id. | 3121 // Store the previous break id and frame id. |
| 3158 break_id_ = debug->break_id(); | 3122 break_id_ = debug->break_id(); |
| 3159 break_frame_id_ = debug->break_frame_id(); | 3123 break_frame_id_ = debug->break_frame_id(); |
| 3160 | 3124 |
| 3161 // Create the new break info. If there is no JavaScript frames there is no | 3125 // Create the new break info. If there is no JavaScript frames there is no |
| 3162 // break frame id. | 3126 // break frame id. |
| 3163 JavaScriptFrameIterator it(isolate_); | 3127 JavaScriptFrameIterator it(isolate_); |
| 3164 has_js_frames_ = !it.done(); | 3128 bool has_js_frames = !it.done(); |
| 3165 debug->thread_local_.break_frame_id_ = has_js_frames_ ? it.frame()->id() | 3129 debug->thread_local_.break_frame_id_ = has_js_frames ? it.frame()->id() |
| 3166 : StackFrame::NO_ID; | 3130 : StackFrame::NO_ID; |
| 3167 debug->SetNextBreakId(); | 3131 debug->SetNextBreakId(); |
| 3168 | 3132 |
| 3169 debug->UpdateState(); | 3133 debug->UpdateState(); |
| 3170 // Make sure that debugger is loaded and enter the debugger context. | 3134 // Make sure that debugger is loaded and enter the debugger context. |
| 3171 // The previous context is kept in save_. | 3135 // The previous context is kept in save_. |
| 3172 load_failed_ = !debug->is_loaded(); | 3136 load_failed_ = !debug->is_loaded(); |
| 3173 if (!load_failed_) isolate_->set_context(*debug->debug_context()); | 3137 if (!load_failed_) isolate_->set_context(*debug->debug_context()); |
| 3174 } | 3138 } |
| 3175 | 3139 |
| 3176 | 3140 |
| 3177 EnterDebugger::~EnterDebugger() { | 3141 EnterDebugger::~EnterDebugger() { |
| 3178 Debug* debug = isolate_->debug(); | 3142 Debug* debug = isolate_->debug(); |
| 3179 | 3143 |
| 3180 // Restore to the previous break state. | 3144 // Restore to the previous break state. |
| 3181 debug->thread_local_.break_frame_id_ = break_frame_id_; | 3145 debug->thread_local_.break_frame_id_ = break_frame_id_; |
| 3182 debug->thread_local_.break_id_ = break_id_; | 3146 debug->thread_local_.break_id_ = break_id_; |
| 3183 | 3147 |
| 3184 // Check for leaving the debugger. | 3148 // Check for leaving the debugger. |
| 3185 if (!load_failed_ && prev_ == NULL) { | 3149 if (!load_failed_ && prev_ == NULL) { |
| 3186 // Clear mirror cache when leaving the debugger. Skip this if there is a | 3150 // Clear mirror cache when leaving the debugger. Skip this if there is a |
| 3187 // pending exception as clearing the mirror cache calls back into | 3151 // pending exception as clearing the mirror cache calls back into |
| 3188 // JavaScript. This can happen if the v8::Debug::Call is used in which | 3152 // JavaScript. This can happen if the v8::Debug::Call is used in which |
| 3189 // case the exception should end up in the calling code. | 3153 // case the exception should end up in the calling code. |
| 3190 if (!isolate_->has_pending_exception()) { | 3154 if (!isolate_->has_pending_exception()) debug->ClearMirrorCache(); |
| 3191 debug->ClearMirrorCache(); | |
| 3192 } | |
| 3193 | 3155 |
| 3194 // If there are commands in the queue when leaving the debugger request | 3156 // If there are commands in the queue when leaving the debugger request |
| 3195 // that these commands are processed. | 3157 // that these commands are processed. |
| 3196 if (debug->has_commands()) isolate_->stack_guard()->RequestDebugCommand(); | 3158 if (debug->has_commands()) isolate_->stack_guard()->RequestDebugCommand(); |
| 3197 } | 3159 } |
| 3198 | 3160 |
| 3199 // Leaving this debugger entry. | 3161 // Leaving this debugger entry. |
| 3200 debug->thread_local_.debugger_entry_ = prev_; | 3162 debug->thread_local_.debugger_entry_ = prev_; |
| 3201 | 3163 |
| 3202 debug->UpdateState(); | 3164 debug->UpdateState(); |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3362 } | 3324 } |
| 3363 | 3325 |
| 3364 | 3326 |
| 3365 CommandMessage::CommandMessage(const Vector<uint16_t>& text, | 3327 CommandMessage::CommandMessage(const Vector<uint16_t>& text, |
| 3366 v8::Debug::ClientData* data) | 3328 v8::Debug::ClientData* data) |
| 3367 : text_(text), | 3329 : text_(text), |
| 3368 client_data_(data) { | 3330 client_data_(data) { |
| 3369 } | 3331 } |
| 3370 | 3332 |
| 3371 | 3333 |
| 3372 CommandMessage::~CommandMessage() { | |
| 3373 } | |
| 3374 | |
| 3375 | |
| 3376 void CommandMessage::Dispose() { | 3334 void CommandMessage::Dispose() { |
| 3377 text_.Dispose(); | 3335 text_.Dispose(); |
| 3378 delete client_data_; | 3336 delete client_data_; |
| 3379 client_data_ = NULL; | 3337 client_data_ = NULL; |
| 3380 } | 3338 } |
| 3381 | 3339 |
| 3382 | 3340 |
| 3383 CommandMessage CommandMessage::New(const Vector<uint16_t>& command, | 3341 CommandMessage CommandMessage::New(const Vector<uint16_t>& command, |
| 3384 v8::Debug::ClientData* data) { | 3342 v8::Debug::ClientData* data) { |
| 3385 return CommandMessage(command.Clone(), data); | 3343 return CommandMessage(command.Clone(), data); |
| 3386 } | 3344 } |
| 3387 | 3345 |
| 3388 | 3346 |
| 3389 CommandMessageQueue::CommandMessageQueue(int size) : start_(0), end_(0), | 3347 CommandMessageQueue::CommandMessageQueue(int size) : start_(0), end_(0), |
| 3390 size_(size) { | 3348 size_(size) { |
| 3391 messages_ = NewArray<CommandMessage>(size); | 3349 messages_ = NewArray<CommandMessage>(size); |
| 3392 } | 3350 } |
| 3393 | 3351 |
| 3394 | 3352 |
| 3395 CommandMessageQueue::~CommandMessageQueue() { | 3353 CommandMessageQueue::~CommandMessageQueue() { |
| 3396 while (!IsEmpty()) { | 3354 while (!IsEmpty()) Get().Dispose(); |
| 3397 CommandMessage m = Get(); | |
| 3398 m.Dispose(); | |
| 3399 } | |
| 3400 DeleteArray(messages_); | 3355 DeleteArray(messages_); |
| 3401 } | 3356 } |
| 3402 | 3357 |
| 3403 | 3358 |
| 3404 CommandMessage CommandMessageQueue::Get() { | 3359 CommandMessage CommandMessageQueue::Get() { |
| 3405 ASSERT(!IsEmpty()); | 3360 ASSERT(!IsEmpty()); |
| 3406 int result = start_; | 3361 int result = start_; |
| 3407 start_ = (start_ + 1) % size_; | 3362 start_ = (start_ + 1) % size_; |
| 3408 return messages_[result]; | 3363 return messages_[result]; |
| 3409 } | 3364 } |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3456 logger_->DebugEvent("Put", message.text()); | 3411 logger_->DebugEvent("Put", message.text()); |
| 3457 } | 3412 } |
| 3458 | 3413 |
| 3459 | 3414 |
| 3460 void LockingCommandMessageQueue::Clear() { | 3415 void LockingCommandMessageQueue::Clear() { |
| 3461 LockGuard<Mutex> lock_guard(&mutex_); | 3416 LockGuard<Mutex> lock_guard(&mutex_); |
| 3462 queue_.Clear(); | 3417 queue_.Clear(); |
| 3463 } | 3418 } |
| 3464 | 3419 |
| 3465 } } // namespace v8::internal | 3420 } } // namespace v8::internal |
| OLD | NEW |